13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_X64)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h"
338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm)
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void ProbeTable(Isolate* isolate,
4344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                       MacroAssembler* masm,
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Code::Flags flags,
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       StubCache::Table table,
463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register receiver,
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Register name,
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       // The offset is scaled by 4, based on
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       // kHeapObjectTagSize, which is two bits
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Register offset) {
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We need to scale up the pointer by 2 because the offset is scaled by less
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // than the pointer size.
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kPointerSizeLog2 == kHeapObjectTagSize + 1);
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ScaleFactor scale_factor = times_2;
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(24, sizeof(StubCache::Entry));
573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // The offset register holds the entry offset times four (due to masking
583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // and shifting optimizations).
5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Multiply by 3 because there are 3 fields per entry (name, code, map).
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lea(offset, Operand(offset, offset, times_2, 0));
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ LoadAddress(kScratchRegister, key_offset);
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the key in the entry matches the name.
693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Multiply entry offset by 16 to get the entry address. Since the
703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // offset register already holds the entry offset times four, multiply
713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // by a further four.
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmpl(name, Operand(kScratchRegister, offset, scale_factor, 0));
735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ j(not_equal, &miss);
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the map entry from the cache.
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use key_offset + kPointerSize * 2, rather than loading map_offset.
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(kScratchRegister,
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Operand(kScratchRegister, offset, scale_factor, kPointerSize * 2));
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmpq(kScratchRegister, FieldOperand(receiver, HeapObject::kMapOffset));
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &miss);
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the code entry from the cache.
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadAddress(kScratchRegister, value_offset);
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(kScratchRegister,
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Operand(kScratchRegister, offset, scale_factor, 0));
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the flags match what we're looking for.
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movl(offset, FieldOperand(kScratchRegister, Code::kFlagsOffset));
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(offset, Immediate(~Code::kFlagsNotUsedInLookup));
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmpl(offset, Immediate(flags));
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&miss);
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&miss);
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the first instruction in the code stub.
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ addq(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag));
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(kScratchRegister);
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Helper function used to check that the dictionary doesn't contain
1103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// the property. This function may return false negatives, so miss_label
1113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// must always call a backup property check that is complete.
1123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// This function is safe to call if the receiver has fast properties.
1133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Name must be a symbol and receiver must be a heap object.
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* miss_label,
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register receiver,
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Handle<String> name,
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register r0,
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register r1) {
1203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(name->IsSymbol());
12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->negative_lookups(), 1);
12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->negative_lookups_miss(), 1);
1243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ movq(r0, FieldOperand(receiver, HeapObject::kMapOffset));
1263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const int kInterceptorOrAccessCheckNeededMask =
1283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
1293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Bail out if the receiver has a named interceptor or requires access checks.
1313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ testb(FieldOperand(r0, Map::kBitFieldOffset),
1323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch           Immediate(kInterceptorOrAccessCheckNeededMask));
1333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ j(not_zero, miss_label);
1343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check that receiver is a JSObject.
1363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE);
1373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ j(below, miss_label);
1383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Load properties array.
1403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register properties = r0;
1413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
1423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check that the properties array is a dictionary.
1443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset),
1453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                 Heap::kHashTableMapRootIndex);
1463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ j(not_equal, miss_label);
1473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringDictionaryLookupStub::GenerateNegativeLookup(masm,
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     miss_label,
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     &done,
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     properties,
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     name,
1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     r1);
1553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ bind(&done);
15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->negative_lookups_miss(), 1);
1573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
1583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm,
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Code::Flags flags,
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register receiver,
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register name,
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register scratch,
1653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                              Register extra,
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register extra2,
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register extra3) {
16844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = masm->isolate();
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  USE(extra);   // The register extra is not used on the X64 platform.
1713e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  USE(extra2);  // The register extra2 is not used on the X64 platform.
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  USE(extra3);  // The register extra2 is not used on the X64 platform.
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Make sure that code is valid. The multiplying code relies on the
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // entry size being 24.
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(sizeof(Entry) == 24);
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the flags do not name a specific type.
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that there are no register conflicts.
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(receiver));
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(name));
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Check scratch register is valid, extra and extra2 are unused.
1853e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!scratch.is(no_reg));
1863e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(extra2.is(no_reg));
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(extra3.is(no_reg));
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Counters* counters = masm->isolate()->counters();
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1);
1913e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(receiver, &miss);
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the map of the receiver and compute the hash.
196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movl(scratch, FieldOperand(name, String::kHashFieldOffset));
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use only the low 32 bits of the map pointer.
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ xor_(scratch, Immediate(flags));
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We mask out the last two bits because they are not part of the hash and
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // they are always 01 for maps.  Also in the two 'and' instructions below.
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the primary table.
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch);
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Primary miss: Compute hash for secondary probe.
208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movl(scratch, FieldOperand(name, String::kHashFieldOffset));
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ xor_(scratch, Immediate(flags));
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ subl(scratch, name);
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ addl(scratch, Immediate(flags));
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch, Immediate((kSecondaryTableSize - 1) << kHeapObjectTagSize));
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the secondary table.
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch);
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache miss: Fall-through and let caller handle the miss by
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // entering the runtime system.
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1);
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
2279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                       int index,
2289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                       Register prototype) {
2299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Load the global or builtins object from the current context.
2309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(prototype,
2319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block             Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
2329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Load the global context from the global or builtins object.
2339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(prototype,
2349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block             FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
2359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Load the function from the global context.
2369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(prototype, Operand(prototype, Context::SlotOffset(index)));
2379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Load the initial map.  The global functions all have initial maps.
2389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(prototype,
2399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block             FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
2409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Load the prototype from the initial map.
2419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
2429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int index,
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register prototype,
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* miss) {
25044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = masm->isolate();
2519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check we're still in the same context.
25244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(prototype, isolate->global());
2539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ cmpq(Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)),
2549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block          prototype);
2559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, miss);
2569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the global function with the given index.
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSFunction> function(
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      JSFunction::cast(isolate->global_context()->get(index)));
2599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Load its initial map. The global functions all have initial maps.
2609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ Move(prototype, Handle<Map>(function->initial_map()));
2619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Load the prototype from the initial map.
2629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch,
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss_label) {
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(receiver, miss_label);
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a JS array.
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, miss_label);
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load length directly from the JS array.
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rax, FieldOperand(receiver, JSArray::kLengthOffset));
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to check if an object is a string.  If the object is
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a string, the map's instance type is left in the scratch register.
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm,
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register receiver,
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register scratch,
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* smi,
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* non_string_object) {
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(receiver, smi);
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a string.
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movzxbq(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
29669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ testl(scratch, Immediate(kNotStringTag));
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_zero, non_string_object);
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register receiver,
304402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register scratch1,
305402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register scratch2,
3061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                            Label* miss,
3071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                            bool support_wrappers) {
308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label check_wrapper;
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the object is a string leaving the instance type in the
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch register.
3121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateStringCheck(masm, receiver, scratch1, miss,
3131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      support_wrappers ? &check_wrapper : miss);
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load length directly from the string.
3166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(rax, FieldOperand(receiver, String::kLengthOffset));
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (support_wrappers) {
3201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check if the object is a JSValue wrapper.
3211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&check_wrapper);
3221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmpl(scratch1, Immediate(JS_VALUE_TYPE));
3231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ j(not_equal, miss);
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check if the wrapped value is a string and load the length
3261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // directly if it is.
3271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
3281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
3291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ movq(rax, FieldOperand(scratch2, String::kLengthOffset));
3301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
3311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
3369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                 Register receiver,
3379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                 Register result,
3389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                 Register scratch,
3399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                 Label* miss_label) {
3409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ TryGetFunctionPrototype(receiver, result, miss_label);
3419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (!result.is(rax)) __ movq(rax, result);
3429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(0);
3439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
3449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
3459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
3469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// Load a fast property out of a holder object (src). In-object properties
3479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// are loaded directly otherwise the property is loaded from the properties
3489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// fixed array.
3499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Register dst,
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Register src,
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Handle<JSObject> holder,
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            int index) {
3549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Adjust for the number of properties stored in the holder.
3559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  index -= holder->map()->inobject_properties();
3569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (index < 0) {
3579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Get the property straight out of the holder.
3589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    int offset = holder->map()->instance_size() + (index * kPointerSize);
3599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(dst, FieldOperand(src, offset));
3609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
3619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Calculate the offset into the properties array.
3629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
3639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset));
3649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(dst, FieldOperand(dst, offset));
3659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
3669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
3679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
3689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
3699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockstatic void PushInterceptorArguments(MacroAssembler* masm,
3709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                     Register receiver,
3719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                     Register holder,
3729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                     Register name,
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<JSObject> holder_obj) {
3749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(name);
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor));
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(kScratchRegister, interceptor);
3789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(kScratchRegister);
3799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(receiver);
3809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(holder);
3819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(FieldOperand(kScratchRegister, InterceptorInfo::kDataOffset));
3829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
3839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
3849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void CompileCallLoadPropertyWithInterceptor(
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register receiver,
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register holder,
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register name,
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder_obj) {
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference ref =
39444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
39544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        masm->isolate());
3968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ Set(rax, 5);
39744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ LoadAddress(rbx, ref);
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CEntryStub stub(1);
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CallStub(&stub);
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Number of pointers to be reserved on stack for fast API call.
4058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangstatic const int kFastApiCallArguments = 3;
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
4088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Reserves space for the extra arguments to API function in the
4096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// caller's frame.
4106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block//
4116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// These arguments are set by CheckPrototypes and GenerateFastApiCall.
4126ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
4136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
4146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[0] : return address
4156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[8] : last argument in the internal frame of the caller
4166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
4176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(scratch, Operand(rsp, 0));
4188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
4196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(Operand(rsp, 0), scratch);
4206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Move(scratch, Smi::FromInt(0));
4218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  for (int i = 1; i <= kFastApiCallArguments; i++) {
4228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang     __ movq(Operand(rsp, i * kPointerSize), scratch);
4238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
4246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Undoes the effects of ReserveSpaceForFastApiCall.
4286ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
4296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
4308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- rsp[0]  : return address.
4318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- rsp[8]  : last fast api call extra argument.
4326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ...
4338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- rsp[kFastApiCallArguments * 8] : first fast api call extra argument.
4348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal
4358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //                                          frame.
4366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
4376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(scratch, Operand(rsp, 0));
4388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch);
4398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments));
4406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Generates call to API function.
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateFastApiCall(MacroAssembler* masm,
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                const CallOptimization& optimization,
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                int argc) {
4476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
4486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[0]              : return address
4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[8]              : object passing the type check
4506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //                           (last fast api call extra argument,
4516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //                            set by CheckPrototypes)
4528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- rsp[16]             : api function
4536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //                           (first fast api call extra argument)
4548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- rsp[24]             : api call data
4558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- rsp[32]             : last argument
4566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ...
4578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- rsp[(argc + 3) * 8] : first argument
4588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- rsp[(argc + 4) * 8] : receiver
4596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
4606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the function and setup the context.
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSFunction> function = optimization.constant_function();
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(rdi, function);
4636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
4646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Pass the additional arguments.
4668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ movq(Operand(rsp, 2 * kPointerSize), rdi);
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> call_data(api_call_info->data());
4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (masm->isolate()->heap()->InNewSpace(*call_data)) {
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(rcx, api_call_info);
4716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
4728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ movq(Operand(rsp, 3 * kPointerSize), rbx);
4736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(Operand(rsp, 3 * kPointerSize), call_data);
4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Prepare arguments.
4788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ lea(rbx, Operand(rsp, 3 * kPointerSize));
4796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#ifdef _WIN64
4818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Win64 uses first register--rcx--for returned value.
4828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register arguments_arg = rdx;
4838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#else
4848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register arguments_arg = rdi;
4858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#endif
4868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Allocate the v8::Arguments structure in the arguments' space since
4888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // it's not controlled by GC.
4898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int kApiStackSpace = 4;
4908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ PrepareCallApiFunction(kApiStackSpace);
4928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ movq(StackSpaceOperand(0), rbx);  // v8::Arguments::implicit_args_.
4948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ addq(rbx, Immediate(argc * kPointerSize));
4958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ movq(StackSpaceOperand(1), rbx);  // v8::Arguments::values_.
4968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Set(StackSpaceOperand(2), argc);  // v8::Arguments::length_.
4978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // v8::Arguments::is_construct_call_.
4988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Set(StackSpaceOperand(3), 0);
4998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // v8::InvocationCallback's argument.
5018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ lea(arguments_arg, StackSpaceOperand(0));
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Function address is a foreign pointer outside V8's heap.
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address function_address = v8::ToCData<Address>(api_call_info->callback());
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallApiFunctionAndReturn(function_address,
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              argc + kFastApiCallArguments + 1);
5076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CallInterceptorCompiler BASE_EMBEDDED {
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
5126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallInterceptorCompiler(StubCompiler* stub_compiler,
5136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          const ParameterCount& arguments,
514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          Register name,
515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          Code::ExtraICState extra_ic_state)
5166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : stub_compiler_(stub_compiler),
5176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        arguments_(arguments),
518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        name_(name),
519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        extra_ic_state_(extra_ic_state) {}
5206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Compile(MacroAssembler* masm,
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Handle<JSObject> object,
5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Handle<JSObject> holder,
5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Handle<String> name,
5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               LookupResult* lookup,
5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register receiver,
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register scratch1,
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register scratch2,
5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register scratch3,
5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Label* miss) {
5316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(holder->HasNamedInterceptor());
5326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
5336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Check that the receiver isn't a smi.
5356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ JumpIfSmi(receiver, miss);
5366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CallOptimization optimization(lookup);
5386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (optimization.is_constant_call()) {
5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       holder, lookup, name, optimization, miss);
5416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     name, holder, miss);
5446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
5456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CompileCacheable(MacroAssembler* masm,
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Handle<JSObject> object,
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register receiver,
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch1,
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch2,
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch3,
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Handle<JSObject> interceptor_holder,
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        LookupResult* lookup,
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Handle<String> name,
5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        const CallOptimization& optimization,
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Label* miss_label) {
5596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(optimization.is_constant_call());
5606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!lookup->holder()->IsGlobalObject());
5616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int depth1 = kInvalidProtoDepth;
5636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int depth2 = kInvalidProtoDepth;
5646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool can_do_fast_api_call = false;
5656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (optimization.is_simple_api_call() &&
5666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        !lookup->holder()->IsGlobalObject()) {
5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      depth1 = optimization.GetPrototypeDepthOfExpectedType(
5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          object, interceptor_holder);
5696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (depth1 == kInvalidProtoDepth) {
5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        depth2 = optimization.GetPrototypeDepthOfExpectedType(
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            interceptor_holder, Handle<JSObject>(lookup->holder()));
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      can_do_fast_api_call =
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Counters* counters = masm->isolate()->counters();
57844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ IncrementCounter(counters->call_const_interceptor(), 1);
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
58144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ReserveSpaceForFastApiCall(masm, scratch1);
5836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
584402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Check that the maps from receiver to interceptor's holder
586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // haven't changed and thus we can invoke interceptor.
5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label miss_cleanup;
5886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
5896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register holder =
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        scratch1, scratch2, scratch3,
5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        name, depth1, miss);
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke an interceptor and if it provides a value,
595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // branch to |regular_invoke|.
5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label regular_invoke;
597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                        &regular_invoke);
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Interceptor returned nothing for this property.  Try to use cached
601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // constant function.
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Check that the maps from interceptor's holder to constant function's
604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // holder haven't changed and thus we can use cached constant function.
6053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (*interceptor_holder != lookup->holder()) {
6067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<JSObject>(lookup->holder()),
6083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      scratch1, scratch2, scratch3,
6093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      name, depth2, miss);
6107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
6117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // CheckPrototypes has a side effect of fetching a 'holder'
6127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // for API (object which is instanceof for the signature).  It's
6137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // safe to omit it here, as if present, it should be fetched
6147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // by the previous CheckPrototypes.
6157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(depth2 == kInvalidProtoDepth);
6167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke function.
6196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateFastApiCall(masm, optimization, arguments_.immediate());
6216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          ? CALL_AS_FUNCTION
624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          : CALL_AS_METHOD;
6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ InvokeFunction(optimization.constant_function(), arguments_,
626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        JUMP_FUNCTION, NullCallWrapper(), call_kind);
6276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Deferred code for fast API call case---clean preallocated space.
6306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
6316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ bind(&miss_cleanup);
6326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FreeSpaceForFastApiCall(masm, scratch1);
6336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ jmp(miss_label);
6346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke a regular function.
6376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ bind(&regular_invoke);
6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
6396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FreeSpaceForFastApiCall(masm, scratch1);
6406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CompileRegular(MacroAssembler* masm,
6443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Handle<JSObject> object,
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register receiver,
6466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Register scratch1,
6476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Register scratch2,
6483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                      Register scratch3,
6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Handle<String> name,
6503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Handle<JSObject> interceptor_holder,
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Label* miss_label) {
6526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register holder =
653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        scratch1, scratch2, scratch3,
6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        name, miss_label);
6566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
658402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Save the name_ register across the call.
659402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(name_);
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
663402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ CallExternalReference(
66444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
66544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          masm->isolate()),
666402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        5);
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Restore the name_ register.
669402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop(name_);
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Leave the internal frame.
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void LoadWithInterceptor(MacroAssembler* masm,
6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register receiver,
6766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register holder,
6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Handle<JSObject> holder_obj,
6786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Label* interceptor_succeeded) {
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FrameScope scope(masm, StackFrame::INTERNAL);
6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(holder);  // Save the holder.
6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(name_);  // Save the name.
6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCallLoadPropertyWithInterceptor(masm,
6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             receiver,
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder,
6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             name_,
6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder_obj);
6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(name_);  // Restore the name.
6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(receiver);  // Restore the holder.
6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Leave the internal frame.
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
6966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ j(not_equal, interceptor_succeeded);
6976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StubCompiler* stub_compiler_;
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const ParameterCount& arguments_;
701402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Register name_;
702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Code::ExtraICState extra_ic_state_;
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
7079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code = (kind == Code::LOAD_IC)
7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? masm->isolate()->builtins()->LoadIC_Miss()
7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : masm->isolate()->builtins()->KeyedLoadIC_Miss();
7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(code, RelocInfo::CODE_TARGET);
7129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
7139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
7149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
7163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code =
7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(code, RelocInfo::CODE_TARGET);
719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// Both name_reg and receiver_reg are preserved on jumps to miss_label,
7239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// but may be destroyed if store is successful.
7249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm,
7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<JSObject> object,
7269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                      int index,
7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<Map> transition,
7289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                      Register receiver_reg,
7299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                      Register name_reg,
7309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                      Register scratch,
7319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                      Label* miss_label) {
7329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the map of the object hasn't changed.
7338f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
7348f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch                                             : REQUIRE_EXACT_MAP;
7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(receiver_reg, Handle<Map>(object->map()),
7368f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch              miss_label, DO_SMI_CHECK, mode);
7379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
7389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Perform global security token check if needed.
7399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (object->IsJSGlobalProxy()) {
7409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
7419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
7429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
7439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Stub never generated for non-global objects that require access
7449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // checks.
7459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
7469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
7479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Perform map transition for the receiver if necessary.
7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) {
7499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // The properties must be extended before we can store the value.
7509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // We jump to a runtime call that extends the properties array.
7519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ pop(scratch);  // Return address.
7529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ push(receiver_reg);
7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Push(transition);
7549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ push(rax);
7559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ push(scratch);
7569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ TailCallExternalReference(
75744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
75844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          masm->isolate()),
75944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        3,
76044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        1);
7619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    return;
7629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
7639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!transition.is_null()) {
7659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Update the map of the object; no write barrier updating is
7669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // needed because the map is never in new space.
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset), transition);
7689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
7699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
7709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Adjust for the number of properties stored in the object. Even in the
7719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // face of a transition we can use the old map here because the size of the
7729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // object and the number of in-object properties is not going to change.
7739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  index -= object->map()->inobject_properties();
7749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
7759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (index < 0) {
7769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Set the property straight into the object.
7779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    int offset = object->map()->instance_size() + (index * kPointerSize);
7789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(FieldOperand(receiver_reg, offset), rax);
7799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
7809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Update the write barrier for the array address.
7819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Pass the value being stored in the now unused name_reg.
7829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(name_reg, rax);
7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(
7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        receiver_reg, offset, name_reg, scratch, kDontSaveFPRegs);
7859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
7869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Write to the properties array.
7879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
7889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Get the properties array (optimistically).
7899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
7909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(FieldOperand(scratch, offset), rax);
7919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
7929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Update the write barrier for the array address.
7939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Pass the value being stored in the now unused name_reg.
7949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(name_reg, rax);
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(
7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        scratch, offset, name_reg, receiver_reg, kDontSaveFPRegs);
7979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
7989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
7999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the value (register rax).
8009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(0);
8019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
8029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
8039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
8049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// Generate code to check that a global property cell is empty. Create
8059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// the property cell at compilation time if no cell exists for the
8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property.
8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCell(MacroAssembler* masm,
8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<GlobalObject> global,
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<String> name,
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Register scratch,
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Label* miss) {
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSGlobalPropertyCell> cell =
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GlobalObject::EnsurePropertyCell(global, name);
8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(cell->value()->IsTheHole());
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(scratch, cell);
8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
81744f0eee88ff00398ff7f715fab053374d808c90dSteve Block         masm->isolate()->factory()->the_hole_value());
8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(not_equal, miss);
8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Calls GenerateCheckPropertyCell for each global object in the prototype chain
8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// from object to (but not including) holder.
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCells(MacroAssembler* masm,
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> object,
8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> holder,
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<String> name,
8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register scratch,
8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Label* miss) {
8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> current = object;
8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!current.is_identical_to(holder)) {
8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (current->IsGlobalObject()) {
8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateCheckPropertyCell(masm,
8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Handle<GlobalObject>::cast(current),
8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                name,
8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                scratch,
8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                miss);
8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    current = Handle<JSObject>(JSObject::cast(current->GetPrototype()));
8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM((masm()))
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister StubCompiler::CheckPrototypes(Handle<JSObject> object,
8489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                       Register object_reg,
8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> holder,
8509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                       Register holder_reg,
8519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                       Register scratch1,
8529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                       Register scratch2,
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<String> name,
8549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                       int save_at_depth,
8559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                       Label* miss) {
8569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Make sure there's no overlap between holder and object registers.
8579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
8589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
8599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block         && !scratch2.is(scratch1));
8609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
8619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Keep track of the current object in register reg.  On the first
8629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // iteration, reg is an alias for object_reg, on later iterations,
8639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // it is an alias for holder_reg.
8649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register reg = object_reg;
8659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  int depth = 0;
8669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
8679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (save_at_depth == depth) {
8689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(Operand(rsp, kPointerSize), object_reg);
8699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
87059151504615d929945dc59db37bf1166937748c6Steve Block
8719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check the maps in the prototype chain.
8729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Traverse the prototype chain from the object and do map checks.
8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> current = object;
8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!current.is_identical_to(holder)) {
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ++depth;
87659151504615d929945dc59db37bf1166937748c6Steve Block
8779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Only global objects and objects that do not require access
8789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // checks are allowed in stubs.
8799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
88059151504615d929945dc59db37bf1166937748c6Steve Block
8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> prototype(JSObject::cast(current->GetPrototype()));
8829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (!current->HasFastProperties() &&
8839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        !current->IsJSGlobalObject() &&
8849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        !current->IsJSGlobalProxy()) {
8859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      if (!name->IsSymbol()) {
8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        name = factory()->LookupSymbol(name);
8879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      }
8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(current->property_dictionary()->FindEntry(*name) ==
8899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block             StringDictionary::kNotFound);
89059151504615d929945dc59db37bf1166937748c6Steve Block
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       scratch1, scratch2);
893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
8949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reg = holder_reg;  // From now on the object will be in holder_reg.
8969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
8973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bool in_new_space = heap()->InNewSpace(*prototype);
8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Map> current_map(current->map());
9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (in_new_space) {
9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Save the map in scratch1 for later.
9029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
9039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      }
9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckMap(reg, Handle<Map>(current_map),
9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
906c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check access rights to the global object.  This has to happen after
9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the map check so that we know that the object is actually a global
9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // object.
9109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      if (current->IsJSGlobalProxy()) {
9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckAccessGlobalProxy(reg, scratch2, miss);
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reg = holder_reg;  // From now on the object will be in holder_reg.
9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (in_new_space) {
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The prototype is in new space; we cannot store a reference to it
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // in the code.  Load it from the map.
9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The prototype is in old space; load it directly.
9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Move(reg, prototype);
9229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      }
9239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
92459151504615d929945dc59db37bf1166937748c6Steve Block
9259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (save_at_depth == depth) {
9269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ movq(Operand(rsp, kPointerSize), reg);
9279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
92859151504615d929945dc59db37bf1166937748c6Steve Block
9299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Go to the next object in the prototype chain.
9309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    current = prototype;
93159151504615d929945dc59db37bf1166937748c6Steve Block  }
9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(current.is_identical_to(holder));
933592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
934592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Log the check depth.
935592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
93659151504615d929945dc59db37bf1166937748c6Steve Block
9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check the holder map.
9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(reg, Handle<Map>(holder->map()),
9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Perform security check for access to the global object.
9429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
9439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (current->IsJSGlobalProxy()) {
9449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ CheckAccessGlobalProxy(reg, scratch1, miss);
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If we've skipped any global objects, it's not enough to verify that
9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // their maps haven't changed.  We also need to check that the property
9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // cell for the property is still empty.
9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the register containing the holder.
9539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return reg;
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadField(Handle<JSObject> object,
9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<JSObject> holder,
9599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                     Register receiver,
9609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                     Register scratch1,
9619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                     Register scratch2,
9629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                     Register scratch3,
9639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                     int index,
9643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<String> name,
9659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                     Label* miss) {
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
9679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(receiver, miss);
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check the prototype chain.
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = CheckPrototypes(
9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the value from the properties.
9749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateFastPropertyLoad(masm(), rax, reg, holder, index);
9759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(0);
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
9803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSObject> holder,
9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register receiver,
9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register name_reg,
9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch1,
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch2,
9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch3,
9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<AccessorInfo> callback,
9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<String> name,
9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Label* miss) {
9899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the receiver isn't a smi.
9909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(receiver, miss);
9916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the maps haven't changed.
9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = CheckPrototypes(object, receiver, holder, scratch1,
9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch2, scratch3, name, miss);
9956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Insert additional parameters into the stack frame above return address.
9979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(!scratch2.is(reg));
9989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ pop(scratch2);  // Get return address to place it below.
9999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(receiver);  // receiver
10019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(reg);  // holder
10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (heap()->InNewSpace(callback->data())) {
10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(scratch1, callback);
10049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset));  // data
10059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Push(Handle<Object>(callback->data()));
10079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
10089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(name_reg);  // name
10099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Save a pointer to where we pushed the arguments pointer.
10109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // This will be passed as the const AccessorInfo& to the C++ callback.
10116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block#ifdef _WIN64
10139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Win64 uses first register--rcx--for returned value.
10149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register accessor_info_arg = r8;
10159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register name_arg = rdx;
10169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block#else
10179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register accessor_info_arg = rsi;
10189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register name_arg = rdi;
10199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block#endif
10206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(!name_arg.is(scratch2));
10229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(name_arg, rsp);
10239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(scratch2);  // Restore return address.
10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 3 elements array for v8::Arguments::values_ and handler for name.
10269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int kStackSpace = 4;
10276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Allocate v8::AccessorInfo in non-GCed stack space.
10299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int kArgStackSpace = 1;
10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ PrepareCallApiFunction(kArgStackSpace);
10329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ lea(rax, Operand(name_arg, 3 * kPointerSize));
10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // v8::AccessorInfo::args_.
10359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(StackSpaceOperand(0), rax);
10366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // The context register (rsi) has been saved in PrepareCallApiFunction and
10389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // could be used to pass arguments.
10399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ lea(accessor_info_arg, StackSpaceOperand(0));
10406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address getter_address = v8::ToCData<Address>(callback->getter());
10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallApiFunctionAndReturn(getter_address, kStackSpace);
10439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
10446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSObject> holder,
10489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                        Register receiver,
10499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                        Register scratch1,
10509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                        Register scratch2,
10519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                        Register scratch3,
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSFunction> value,
10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<String> name,
10549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                        Label* miss) {
10559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the receiver isn't a smi.
10569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(receiver, miss);
10576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the maps haven't changed.
10593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(
10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
10619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the constant value.
10633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(rax, value);
10649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(0);
10659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
10666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
10693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Handle<JSObject> interceptor_holder,
10709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                           LookupResult* lookup,
10719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                           Register receiver,
10729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                           Register name_reg,
10739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                           Register scratch1,
10749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                           Register scratch2,
10759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                           Register scratch3,
10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Handle<String> name,
10779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                           Label* miss) {
10789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(interceptor_holder->HasNamedInterceptor());
10799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
10806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the receiver isn't a smi.
10829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(receiver, miss);
10836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // So far the most popular follow ups for interceptor loads are FIELD
10859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // and CALLBACKS, so inline only them, other cases may be added
10869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // later.
10879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  bool compile_followup_inline = false;
10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (lookup->IsFound() && lookup->IsCacheable()) {
10899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (lookup->type() == FIELD) {
10909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      compile_followup_inline = true;
10919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    } else if (lookup->type() == CALLBACKS &&
10923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               lookup->GetCallbackObject()->IsAccessorInfo()) {
10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      compile_followup_inline =
10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL;
10959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
10969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
10979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (compile_followup_inline) {
10999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Compile the interceptor call, followed by inline code to load the
11009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // property from further up the prototype chain if the call fails.
11019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Check that the maps haven't changed.
11029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
11039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                          scratch1, scratch2, scratch3,
11049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                          name, miss);
11059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11075710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    // Preserve the receiver register explicitly whenever it is different from
11085710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    // the holder and it is needed should the interceptor return without any
11095710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    // result. The CALLBACKS case needs the receiver to be passed into C++ code,
11105710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    // the FIELD case might cause a miss during the prototype check.
11115710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
11125710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    bool must_preserve_receiver_reg = !receiver.is(holder_reg) &&
11135710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch        (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
11145710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch
11159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Save necessary data before invoking an interceptor.
11169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Requires a frame to make GC aware of pushed pointers.
11173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FrameScope frame_scope(masm(), StackFrame::INTERNAL);
11196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11205710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch      if (must_preserve_receiver_reg) {
11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ push(receiver);
11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(holder_reg);
11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(name_reg);
1125592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
11263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Invoke an interceptor.  Note: map checks from receiver to
11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // interceptor's holder has been compiled before (see a caller
11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // of this method.)
11293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCallLoadPropertyWithInterceptor(masm(),
11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             receiver,
11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder_reg,
11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             name_reg,
11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             interceptor_holder);
11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if interceptor provided a value for property.  If it's
11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the case, return immediately.
11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label interceptor_failed;
11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(equal, &interceptor_failed);
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      frame_scope.GenerateLeaveFrame();
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ret(0);
11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&interceptor_failed);
11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(name_reg);
11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(holder_reg);
11465710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch      if (must_preserve_receiver_reg) {
11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ pop(receiver);
11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
11496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Leave the internal frame.
11513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
115285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
11539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Check that the maps from interceptor's holder to lookup's holder
11549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // haven't changed.  And load lookup's holder into |holder| register.
11555710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    if (must_perfrom_prototype_check) {
11569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      holder_reg = CheckPrototypes(interceptor_holder,
11579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                   holder_reg,
11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Handle<JSObject>(lookup->holder()),
11599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                   scratch1,
11609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                   scratch2,
11619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                   scratch3,
11629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                   name,
11639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                   miss);
11649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
11656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (lookup->type() == FIELD) {
11679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // We found FIELD property in prototype chain of interceptor's holder.
11689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Retrieve a field from field's holder.
11699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      GenerateFastPropertyLoad(masm(), rax, holder_reg,
11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Handle<JSObject>(lookup->holder()),
11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               lookup->GetFieldIndex());
11729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ ret(0);
11739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    } else {
11749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // We found CALLBACKS property in prototype chain of interceptor's
11759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // holder.
11769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ASSERT(lookup->type() == CALLBACKS);
11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<AccessorInfo> callback(
11783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject()));
11799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ASSERT(callback->getter() != NULL);
1180756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
11819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Tail call to runtime.
11829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Important invariant in CALLBACKS case: the code above must be
11839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // structured to never clobber |receiver| register.
11849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ pop(scratch2);  // return address
11859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ push(receiver);
11869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ push(holder_reg);
11873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Move(holder_reg, callback);
11889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
11899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ push(holder_reg);
11909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ push(name_reg);
11919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ push(scratch2);  // restore return address
1192756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
11939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ExternalReference ref =
119444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
119544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            isolate());
11969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ TailCallExternalReference(ref, 5, 1);
11976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
11989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {  // !compile_followup_inline
11999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Call the runtime system to load the interceptor.
12009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Check that the maps haven't changed.
12019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
12029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                          scratch1, scratch2, scratch3,
12039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                          name, miss);
12049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ pop(scratch2);  // save old return address
12059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    PushInterceptorArguments(masm(), receiver, holder_reg,
12069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                             name_reg, interceptor_holder);
12079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ push(scratch2);  // restore old return address
12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    ExternalReference ref = ExternalReference(
121044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate());
12119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ TailCallExternalReference(ref, 5, 1);
12125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
12136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
12179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (kind_ == Code::KEYED_CALL_IC) {
12183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Cmp(rcx, name);
12199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ j(not_equal, miss);
12209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
12219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
12226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
12253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
12263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
12279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                   Label* miss) {
12289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(holder->IsGlobalObject());
12296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the number of arguments.
12319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
12329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack.
12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
12356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the maps haven't changed.
12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(rdx, miss);
12399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss);
12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell(
12443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
12453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* miss) {
12479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the value from the cell.
12483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rdi, cell);
12499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset));
125080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
12519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the cell contains the same function.
12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (heap()->InNewSpace(*function)) {
12539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // We can't embed a pointer to a function in new space so we have
12549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // to verify that the shared function info is unchanged. This has
12559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // the nice side effect that multiple closures based on the same
12569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // function can all use this call IC. Before we load through the
12579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // function, we have to verify that it still is a function.
12589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ JumpIfSmi(rdi, miss);
12599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax);
12609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ j(not_equal, miss);
126180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
12629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Check the shared function info. Make sure it hasn't changed.
12639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ Move(rax, Handle<SharedFunctionInfo>(function->shared()));
12649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax);
126580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Cmp(rdi, function);
126780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, miss);
12699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
127080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
127180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() {
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code =
1274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                               kind_,
12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               extra_state_);
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(code, RelocInfo::CODE_TARGET);
12787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
12797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
12839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                int index,
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
128580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ----------- S t a t e -------------
12869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rcx                 : function name
12879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[0]              : return address
12889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[8]              : argument argc
12899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[16]             : argument argc - 1
12909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ...
12919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[argc * 8]       : argument 1
12929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[(argc + 1) * 8] : argument 0 = receiver
129380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // -----------------------------------
129480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label miss;
12959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
129680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateNameCheck(name, &miss);
129780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
12989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the receiver from the stack.
12999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
13009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
130180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
13029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the receiver isn't a smi.
13039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(rdx, &miss);
130480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
13059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Do the right check and compute the holder register.
13069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi,
13079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                 name, &miss);
130880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
13099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateFastPropertyLoad(masm(), rdi, reg, holder, index);
131080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
13119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the function really is a function.
13129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(rdi, &miss);
13139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx);
13149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
13159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
13169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Patch the receiver on the stack with the global proxy if
13179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // necessary.
13189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (object->IsGlobalObject()) {
13199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
13209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
13219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
13229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
13239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Invoke the function.
13243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
1326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
13297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Handle call cache miss.
133180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&miss);
13323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
133380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
133480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Return the generated code.
13359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(FIELD, name);
133680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
13376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13393ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall(
13403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
134559151504615d929945dc59db37bf1166937748c6Steve Block  // ----------- S t a t e -------------
13469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx                 : name
134759151504615d929945dc59db37bf1166937748c6Steve Block  //  -- rsp[0]              : return address
134859151504615d929945dc59db37bf1166937748c6Steve Block  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
134959151504615d929945dc59db37bf1166937748c6Steve Block  //  -- ...
135059151504615d929945dc59db37bf1166937748c6Steve Block  //  -- rsp[(argc + 1) * 8] : receiver
135159151504615d929945dc59db37bf1166937748c6Steve Block  // -----------------------------------
135259151504615d929945dc59db37bf1166937748c6Steve Block
13539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If object is not an array, bail out to regular call.
13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
135559151504615d929945dc59db37bf1166937748c6Steve Block
135659151504615d929945dc59db37bf1166937748c6Steve Block  Label miss;
135759151504615d929945dc59db37bf1166937748c6Steve Block  GenerateNameCheck(name, &miss);
135859151504615d929945dc59db37bf1166937748c6Steve Block
13599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the receiver from the stack.
13609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
13619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
136259151504615d929945dc59db37bf1166937748c6Steve Block
13639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the receiver isn't a smi.
13649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(rdx, &miss);
136559151504615d929945dc59db37bf1166937748c6Steve Block
13663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, &miss);
13689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
13699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (argc == 0) {
13709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Noop, return the length.
13719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
13729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ ret((argc + 1) * kPointerSize);
137359151504615d929945dc59db37bf1166937748c6Steve Block  } else {
13749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Label call_builtin;
137559151504615d929945dc59db37bf1166937748c6Steve Block
13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (argc == 1) {  // Otherwise fall through to call builtin.
13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label attempt_to_grow_elements, with_write_barrier;
137859151504615d929945dc59db37bf1166937748c6Steve Block
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements array of the object.
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
13815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check that the elements are in fast mode and writable.
13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             factory()->fixed_array_map());
13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &call_builtin);
13865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
13879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Get the array's length into rax and calculate new length.
13889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
13899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
13909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ addl(rax, Immediate(argc));
139159151504615d929945dc59db37bf1166937748c6Steve Block
13923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements' length into rcx.
13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
139459151504615d929945dc59db37bf1166937748c6Steve Block
13959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Check if we could survive without allocation.
13969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ cmpl(rax, rcx);
13979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ j(greater, &attempt_to_grow_elements);
13989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if value is a smi.
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rcx, Operand(rsp, argc * kPointerSize));
14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfNotSmi(rcx, &with_write_barrier);
14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Save new length.
14049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
14059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(FieldOperand(rdi,
14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           rax,
14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           times_pointer_size,
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           FixedArray::kHeaderSize - argc * kPointerSize),
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              rcx);
14129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ Integer32ToSmi(rax, rax);  // Return new length as smi.
141485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      __ ret((argc + 1) * kPointerSize);
14159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
141685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      __ bind(&with_write_barrier);
14179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
14193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_smi_only_arrays  && !FLAG_trace_elements_transitions) {
14213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label fast_object, not_fast_object;
14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(rbx, &not_fast_object, Label::kNear);
14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&fast_object);
14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // In case of fast smi-only, convert to fast object, otherwise bail out.
14253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&not_fast_object);
14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastSmiOnlyElements(rbx, &call_builtin);
14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // rdx: receiver
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // rbx: map
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ movq(r9, rdi);  // Backup rdi as it is going to be trashed.
14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               FAST_ELEMENTS,
14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               rbx,
14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               rdi,
14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               &call_builtin);
14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm());
14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ movq(rdi, r9);
14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&fast_object);
14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(rbx, &call_builtin);
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Save new length.
14433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
14463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lea(rdx, FieldOperand(rdi,
14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               rax, times_pointer_size,
14483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               FixedArray::kHeaderSize - argc * kPointerSize));
14493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(Operand(rdx, 0), rcx);
1450592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
14513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWrite(rdi, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     OMIT_SMI_CHECK);
1453592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Integer32ToSmi(rax, rax);  // Return new length as smi.
14559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ ret((argc + 1) * kPointerSize);
14569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ bind(&attempt_to_grow_elements);
14589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      if (!FLAG_inline_new) {
14599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ jmp(&call_builtin);
14609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      }
14619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rbx, Operand(rsp, argc * kPointerSize));
14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Growing elements that are SMI-only requires special handling in case
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the new element is non-Smi. For now, delegate to the builtin.
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label no_fast_elements_check;
14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfSmi(rbx, &no_fast_elements_check);
14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar);
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&no_fast_elements_check);
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ExternalReference new_space_allocation_top =
147244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_top_address(isolate());
14739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ExternalReference new_space_allocation_limit =
147444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_limit_address(isolate());
14759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      const int kAllocationDelta = 4;
14779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Load top.
147844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ Load(rcx, new_space_allocation_top);
14799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Check if it's the end of elements.
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lea(rdx, FieldOperand(rdi,
14829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                               rax, times_pointer_size,
14839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                               FixedArray::kHeaderSize - argc * kPointerSize));
14849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ cmpq(rdx, rcx);
14859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ j(not_equal, &call_builtin);
14869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ addq(rcx, Immediate(kAllocationDelta * kPointerSize));
148744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Operand limit_operand =
148844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          masm()->ExternalOperand(new_space_allocation_limit);
148944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ cmpq(rcx, limit_operand);
14909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ j(above, &call_builtin);
14919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // We fit and could grow elements.
149344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ Store(new_space_allocation_top, rcx);
14949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Push the argument...
14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(Operand(rdx, 0), rbx);
14979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // ... and fill the rest with holes.
14989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
14999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      for (int i = 1; i < kAllocationDelta; i++) {
15009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ movq(Operand(rdx, i * kPointerSize), kScratchRegister);
15019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      }
15029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // We know the elements array is in new space so we don't need the
15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // remembered set, but we just pushed a value onto it so we may have to
15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // tell the incremental marker to rescan the object that we just grew.  We
15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // don't need to worry about the holes because they are in old space and
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // already marked black.
15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Restore receiver to rdx as finish sequence assumes it's here.
15119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
15129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
15139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Increment element's and array's sizes.
15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset),
15159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                        Smi::FromInt(kAllocationDelta));
15169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
15179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Make new length a smi before returning it.
15189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ Integer32ToSmi(rax, rax);
15199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax);
15209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
15219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ ret((argc + 1) * kPointerSize);
15229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
15239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
15249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ bind(&call_builtin);
152544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
152644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   isolate()),
15279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                 argc + 1,
15289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                 1);
15299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
153059151504615d929945dc59db37bf1166937748c6Steve Block
153159151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&miss);
15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
153359151504615d929945dc59db37bf1166937748c6Steve Block
153459151504615d929945dc59db37bf1166937748c6Steve Block  // Return the generated code.
15359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(function);
15360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
15370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
15380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall(
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1545f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // ----------- S t a t e -------------
15469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx                 : name
1547f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- rsp[0]              : return address
1548f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1549f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- ...
1550f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- rsp[(argc + 1) * 8] : receiver
1551f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // -----------------------------------
1552f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If object is not an array, bail out to regular call.
15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
1555f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss, return_undefined, call_builtin;
1557f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  GenerateNameCheck(name, &miss);
1558f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the receiver from the stack.
15609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
15619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1562f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the receiver isn't a smi.
15649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(rdx, &miss);
1565f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, &miss);
1568f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the elements array of the object.
15709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
1571f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the elements are in fast mode and writable.
15739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
15749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                 Heap::kFixedArrayMapRootIndex);
15759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &call_builtin);
1576f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the array's length into rcx and calculate new length.
15789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
15799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ subl(rcx, Immediate(1));
15809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(negative, &return_undefined);
1581f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the last element.
15839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ LoadRoot(r9, Heap::kTheHoleValueRootIndex);
15849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rax, FieldOperand(rbx,
15859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                            rcx, times_pointer_size,
15869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                            FixedArray::kHeaderSize));
15879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check if element is already the hole.
15889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ cmpq(rax, r9);
15899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If so, call slow-case to also check prototypes for value.
15909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(equal, &call_builtin);
1591f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Set the array's length.
15939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
1594f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Fill with the hole and return original value.
15969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(FieldOperand(rbx,
15979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                       rcx, times_pointer_size,
15989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                       FixedArray::kHeaderSize),
15999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block          r9);
16009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret((argc + 1) * kPointerSize);
1601f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
16029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&return_undefined);
16039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
16049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret((argc + 1) * kPointerSize);
1605f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
16069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&call_builtin);
160744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ TailCallExternalReference(
160844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(Builtins::c_ArrayPop, isolate()),
160944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      argc + 1,
161044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      1);
1611f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1612f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&miss);
16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1614f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1615f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Return the generated code.
16169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(function);
1617f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
1618f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1619f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
16279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx                 : function name
16289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]              : return address
16299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
16309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- ...
16319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc + 1) * 8] : receiver
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If object is not a string, bail out to regular call.
16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
16369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
1640b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
16419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label index_out_of_range;
1642b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
1643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
16443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1646b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1647b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1648b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the maps starting from the prototype haven't changed.
16519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateDirectLoadGlobalFunctionPrototype(masm(),
16529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                            Context::STRING_FUNCTION_INDEX,
16539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                            rax,
16549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                            &miss);
16553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
16573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  rax, holder, rbx, rdx, rdi, name, &miss);
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register receiver = rbx;
16609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register index = rdi;
16619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register result = rax;
16629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
16639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (argc > 0) {
16649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(index, Operand(rsp, (argc - 0) * kPointerSize));
16659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
16669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
16679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharCodeAtGenerator generator(receiver,
16703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index,
16713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      result,
16723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a string.
16733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a number.
16743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index_out_of_range_label,
16753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      STRING_INDEX_IS_NUMBER);
16763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
16779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret((argc + 1) * kPointerSize);
1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  StubRuntimeCallHelper call_helper;
16803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1682b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1683b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
1684b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ LoadRoot(rax, Heap::kNanValueRootIndex);
1685b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ ret((argc + 1) * kPointerSize);
1686b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1689b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in rcx.
16903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rcx, name);
1691b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
16923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
16959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(function);
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall(
17003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
17013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
17023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
17033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
17043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
17069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx                 : function name
17079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]              : return address
17089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
17099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- ...
17109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc + 1) * 8] : receiver
171159151504615d929945dc59db37bf1166937748c6Steve Block  // -----------------------------------
171259151504615d929945dc59db37bf1166937748c6Steve Block
17139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If object is not a string, bail out to regular call.
17143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
17159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
17169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1718b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
17199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label index_out_of_range;
1720b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
17223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1724b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1725b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1726b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
17279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
17289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the maps starting from the prototype haven't changed.
17299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateDirectLoadGlobalFunctionPrototype(masm(),
17309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                            Context::STRING_FUNCTION_INDEX,
17319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                            rax,
17329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                            &miss);
17333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
17343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
17353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  rax, holder, rbx, rdx, rdi, name, &miss);
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register receiver = rax;
17389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register index = rdi;
17393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = rdx;
17409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register result = rax;
17419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
17429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (argc > 0) {
17439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(index, Operand(rsp, (argc - 0) * kPointerSize));
17449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
17459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharAtGenerator generator(receiver,
17493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index,
17503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  scratch,
17513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  result,
17523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a string.
17533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a number.
17543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index_out_of_range_label,
17553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  STRING_INDEX_IS_NUMBER);
17563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
17579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret((argc + 1) * kPointerSize);
17589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
17599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  StubRuntimeCallHelper call_helper;
17603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1762b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1763b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
1764b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ LoadRoot(rax, Heap::kEmptyStringRootIndex);
1765b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ ret((argc + 1) * kPointerSize);
1766b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1768b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in rcx.
17693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rcx, name);
1770b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
17749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(function);
1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17783ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
17793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
17803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
17813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
17823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
17833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
17859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx                 : function name
17869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]              : return address
17879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
17889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- ...
17899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc + 1) * 8] : receiver
1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If the object is not a JSObject or we got an unexpected number of
17939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // arguments, bail out to the regular call.
17943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int argc = arguments().immediate();
17953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
17989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateNameCheck(name, &miss);
1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
18019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rdx, Operand(rsp, 2 * kPointerSize));
18029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ JumpIfSmi(rdx, &miss);
18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
18043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
18059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
18063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
18073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
18083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
18099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    GenerateLoadFunctionFromCell(cell, function, &miss);
18109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Load the char code argument.
18139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register code = rbx;
18149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(code, Operand(rsp, 1 * kPointerSize));
18156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check the code is a smi.
18179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label slow;
18189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfNotSmi(code, &slow);
18196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Convert the smi code to uint16.
18219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ SmiAndConstant(code, code, Smi::FromInt(0xffff));
18226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharFromCodeGenerator generator(code, rax);
18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
18259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(2 * kPointerSize);
18266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  StubRuntimeCallHelper call_helper;
18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
18299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
18309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Tail call the full function. We do not have to patch the receiver
18319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // because the function makes no use of it.
18329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&slow);
18333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
1835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
1836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
1837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
18386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
18409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rcx: function name.
18413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
18426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
18443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
18456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
18466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall(
18493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
18503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
18513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
18523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
18533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
18549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // TODO(872): implement this.
18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return Handle<Code>::null();
1856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18593ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall(
18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
18613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
18623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
18633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
18643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
18669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx                 : function name
18679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]              : return address
18689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
18699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- ...
18709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc + 1) * 8] : receiver
1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
18729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
18739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If the object is not a JSObject or we got an unexpected number of
18749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // arguments, bail out to the regular call.
18753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int argc = arguments().immediate();
18763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
18779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
18799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateNameCheck(name, &miss);
1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
18829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rdx, Operand(rsp, 2 * kPointerSize));
18839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ JumpIfSmi(rdx, &miss);
18843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
18853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
18869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
18873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
18883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
18909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    GenerateLoadFunctionFromCell(cell, function, &miss);
18919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
18929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Load the (only) argument into rax.
18939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rax, Operand(rsp, 1 * kPointerSize));
1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check if the argument is a smi.
18969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label not_smi;
18979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  STATIC_ASSERT(kSmiTag == 0);
18989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfNotSmi(rax, &not_smi);
18999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ SmiToInteger32(rax, rax);
1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
19029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // otherwise.
19039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movl(rbx, rax);
19049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ sarl(rbx, Immediate(kBitsPerInt - 1));
1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Do bitwise not or do nothing depending on ebx.
19079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ xorl(rax, rbx);
1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Add 1 or do nothing depending on ebx.
19109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ subl(rax, rbx);
19119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
19129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If the result is still negative, go to the slow case.
19139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // This only happens for the most negative smi.
19149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label slow;
19159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(negative, &slow);
19169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
19179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Smi case done.
19189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ Integer32ToSmi(rax, rax);
19199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(2 * kPointerSize);
19209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
19219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check if the argument is a heap number and load its value.
19229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&not_smi);
1923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
19249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check the sign of the argument. If the argument is positive,
19279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // just return it.
19289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label negative_sign;
19299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int sign_mask_shift =
19309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      (HeapNumber::kExponentOffset - HeapNumber::kValueOffset) * kBitsPerByte;
19319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdi, static_cast<int64_t>(HeapNumber::kSignMask) << sign_mask_shift,
19329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block          RelocInfo::NONE);
19339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ testq(rbx, rdi);
19349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_zero, &negative_sign);
19359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(2 * kPointerSize);
1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If the argument is negative, clear the sign, and return a new
19389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // number. We still have the sign mask in rdi.
19399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&negative_sign);
19409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ xor_(rbx, rdi);
19419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ AllocateHeapNumber(rax, rdx, &slow);
19429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx);
19439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(2 * kPointerSize);
1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Tail call the full function. We do not have to patch the receiver
19469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // because the function makes no use of it.
19479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&slow);
19483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
1950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
1951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
1952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
1953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
19559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rcx: function name.
19563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
19593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19633ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall(
196444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    const CallOptimization& optimization,
19653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
19683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
19693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
197044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(optimization.is_simple_api_call());
197144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Bail out if object is a global object as we don't want to
197244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // repatch it to global receiver.
19733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (object->IsGlobalObject()) return Handle<Code>::null();
19743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!cell.is_null()) return Handle<Code>::null();
19753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject()) return Handle<Code>::null();
197644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int depth = optimization.GetPrototypeDepthOfExpectedType(
19773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<JSObject>::cast(object), holder);
19783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (depth == kInvalidProtoDepth) return Handle<Code>::null();
197944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
198044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss, miss_before_stack_reserved;
198144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss_before_stack_reserved);
198244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
198344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the receiver from the stack.
198444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int argc = arguments().immediate();
198544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
198644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
198744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the receiver isn't a smi.
198844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ JumpIfSmi(rdx, &miss_before_stack_reserved);
198944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
199044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
199144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const(), 1);
199244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const_fast_api(), 1);
199344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
199444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate space for v8::Arguments implicit values. Must be initialized
199544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // before calling any runtime function.
199644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
199744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
199844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the maps haven't changed and find a Holder as a side effect.
19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
20003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, depth, &miss);
200144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
200244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Move the return address on top of the stack.
200344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(rax, Operand(rsp, 3 * kPointerSize));
200444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(Operand(rsp, 0 * kPointerSize), rax);
200544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateFastApiCall(masm(), optimization, argc);
200744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
200844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss);
200944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
201044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
201144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss_before_stack_reserved);
20123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
201344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
201444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Return the generated code.
201544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return GetCode(function);
201644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
201744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
201844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
20193ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
20203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
20213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> function,
20223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
20239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                   CheckType check) {
2024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
20259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rcx                 : function name
20269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[0]              : return address
20279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[8]              : argument argc
20289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[16]             : argument argc - 1
20299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ...
20309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[argc * 8]       : argument 1
20319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[(argc + 1) * 8] : argument 0 = receiver
2032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
203444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
20353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder,
20363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Handle<JSGlobalPropertyCell>::null(),
20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          function, name);
20383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
20393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
20400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
2041e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
204244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss;
204344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss);
2044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the receiver from the stack.
20469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
20479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
2048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the receiver isn't a smi.
20509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (check != NUMBER_CHECK) {
205144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ JumpIfSmi(rdx, &miss);
20529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Make sure that it's okay not to patch the on stack receiver
20559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // unless we're doing a receiver map check.
20569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
205844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
20599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  switch (check) {
20609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    case RECEIVER_MAP_CHECK:
206144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ IncrementCounter(counters->call_const(), 1);
2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Check that the maps haven't changed.
20643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax,
20653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      rdi, name, &miss);
2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Patch the receiver on the stack with the global proxy if
20689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // necessary.
20699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      if (object->IsGlobalObject()) {
20709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
20719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
20729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      }
20739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      break;
2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    case STRING_CHECK:
20763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
20779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        // Check that the object is a two-byte string or a symbol.
20789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax);
20799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ j(above_equal, &miss);
20809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        // Check that the maps starting from the prototype haven't changed.
20819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        GenerateDirectLoadGlobalFunctionPrototype(
20829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block            masm(), Context::STRING_FUNCTION_INDEX, rax, &miss);
20833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
20843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
20853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            rax, holder, rbx, rdx, rdi, name, &miss);
20863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
208785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
208885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // requires boxing.
208985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        __ jmp(&miss);
20903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
20913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
20923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case NUMBER_CHECK:
20943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
20959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        Label fast;
20969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        // Check that the object is a smi or a heap number.
20979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ JumpIfSmi(rdx, &fast);
20989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax);
20999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ j(not_equal, &miss);
21009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ bind(&fast);
21019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        // Check that the maps starting from the prototype haven't changed.
21029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        GenerateDirectLoadGlobalFunctionPrototype(
21039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block            masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss);
21043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
21053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
21063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            rax, holder, rbx, rdx, rdi, name, &miss);
21073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
210885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
210985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // requires boxing.
211085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        __ jmp(&miss);
21113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
21123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
21133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case BOOLEAN_CHECK:
21153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
21169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        Label fast;
21179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        // Check that the object is a boolean.
21189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ CompareRoot(rdx, Heap::kTrueValueRootIndex);
21199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ j(equal, &fast);
21209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ CompareRoot(rdx, Heap::kFalseValueRootIndex);
21219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ j(not_equal, &miss);
21229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ bind(&fast);
21239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        // Check that the maps starting from the prototype haven't changed.
21249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        GenerateDirectLoadGlobalFunctionPrototype(
21259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block            masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss);
21263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
21273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
21283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            rax, holder, rbx, rdx, rdi, name, &miss);
21293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
21313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // requires boxing.
21323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&miss);
21339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      }
21349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      break;
21359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
2136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
2140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Handle call cache miss.
2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
21489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(function);
2149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21523ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
21533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
21543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
21569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rcx                 : function name
21579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[0]              : return address
21589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[8]              : argument argc
21599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[16]             : argument argc - 1
21609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ...
21619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[argc * 8]       : argument 1
21629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[(argc + 1) * 8] : argument 0 = receiver
2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
21659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateNameCheck(name, &miss);
2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the number of arguments.
21689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
21729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
21739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the receiver from the stack.
21749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
21759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
21763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_);
21773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax,
21783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   &miss);
21799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
21809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Restore receiver.
21819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
21829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
21839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the function really is a function.
21849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(rax, &miss);
21859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
21869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
21879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
21889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Patch the receiver on the stack with the global proxy if
21899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // necessary.
21909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (object->IsGlobalObject()) {
21919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
21929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
21939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
21949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
21959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Invoke the function.
21969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdi, rax);
21973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
2200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
2201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
22029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
22039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Handle load cache miss.
2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
22053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22123ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal(
22133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
22143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
22153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
22163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
22173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
22199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rcx                 : function name
22209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[0]              : return address
22219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[8]              : argument argc
22229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[16]             : argument argc - 1
22239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ...
22249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[argc * 8]       : argument 1
22259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[(argc + 1) * 8] : argument 0 = receiver
2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
22279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
222844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
22293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
22303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
22313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
22329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
22339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
2234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
22359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateNameCheck(name, &miss);
2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the number of arguments.
22389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
22399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateGlobalReceiverCheck(object, holder, name, &miss);
22409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadFunctionFromCell(cell, function, &miss);
22419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
22429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Patch the receiver on the stack with the global proxy.
22439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (object->IsGlobalObject()) {
22449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
22459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
22469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
22479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the context (function already in rdi).
22499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
22509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
22519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Jump to the cached code (tail call).
225244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
225344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline(), 1);
22549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ParameterCount expected(function->shared()->formal_parameter_count());
22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We call indirectly through the code field in the function to
22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // allow recompilation to take effect without changing any of the
22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // call sites.
22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION,
22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                NullCallWrapper(), call_kind);
22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Handle call cache miss.
2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
226744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline_miss(), 1);
22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
22719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(NORMAL, name);
2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22753ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
22769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                  int index,
22773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<Map> transition,
22783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<String> name) {
2279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
22809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : value
22819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
2282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rdx    : receiver
22839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
2284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
2285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label miss;
2286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Generate store field code.  Preserves receiver and name on jump to miss.
22883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss);
2289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Handle store cache miss.
2291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
229244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
22939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Return the generated code.
22963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback(
23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback,
23033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax    : value
2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
23074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- rdx    : receiver
2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
23133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(rdx, Handle<Map>(object->map()), &miss,
23143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
23184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ CheckAccessGlobalProxy(rdx, rbx, &miss);
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(rbx);  // remove the return address
23269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rdx);  // receiver
23273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(callback);  // callback info
23289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rcx);  // name
23299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rax);  // value
23309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rbx);  // restore return address
23319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
23329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Do tail-call to the runtime system.
23339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ExternalReference store_callback_property =
233444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
23359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ TailCallExternalReference(store_callback_property, 4, 1);
2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
233944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
23439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CALLBACKS, name);
2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23473ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor(
23483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
23493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax    : value
2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
23534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- rdx    : receiver
2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
23593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss,
23603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (receiver->IsJSGlobalProxy()) {
23644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ CheckAccessGlobalProxy(rdx, rbx, &miss);
2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(rbx);  // remove the return address
23724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(rdx);  // receiver
2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rcx);  // name
2374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rax);  // value
2375e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ Push(Smi::FromInt(strict_mode_));
2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rbx);  // restore return address
2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_ic_property =
238044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
2381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ TailCallExternalReference(store_ic_property, 4, 1);
2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
238544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23933ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal(
23943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> object,
23953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
23963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax    : value
2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
24004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- rdx    : receiver
2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
24064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Handle<Map>(object->map()));
2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Compute the cell operand to use.
24113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rbx, cell);
24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Operand cell_operand = FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset);
24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the value in the cell is not the hole. If it is, this
24151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // cell could have been deleted and reintroducing the global needs
24161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // to update the property details in the property dictionary of the
24171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // global object. We bail out to the runtime system to do that.
24183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareRoot(cell_operand, Heap::kTheHoleValueRootIndex);
24191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ j(equal, &miss);
24201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Store the value in the cell.
24223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(cell_operand, rax);
24233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Cells are always rescanned, so no write barrier here.
2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the value (register rax).
242644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
242744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline(), 1);
2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
243244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
243344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24413ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
24425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                       int index,
24433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<Map> transition,
24443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<String> name) {
2445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax     : value
2447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- rcx     : key
2448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- rdx     : receiver
2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0]  : return address
2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
245344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
245444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_store_field(), 1);
2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
24573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rcx, name);
2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Generate store field code.  Preserves receiver and name on jump to miss.
24613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss);
2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
246544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_store_field(), 1);
246644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24743ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement(
24753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
2476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
2477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rax    : value
2478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rcx    : key
2479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rdx    : receiver
2480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rsp[0] : return address
2481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
24823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2483589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
2484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
24853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub =
24863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode();
24873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
2489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
2492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
24943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
2495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
24983ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
24993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
25003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_stubs,
25013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* transitioned_maps) {
2502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : value
2504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rcx    : key
2505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
2506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0] : return address
2507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
25093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(rdx, &miss, Label::kNear);
2510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
2512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int receiver_count = receiver_maps->length();
25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < receiver_count; ++i) {
2514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check map and tail call if there's a match
25153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Cmp(rdi, receiver_maps->at(i));
25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (transitioned_maps->at(i).is_null()) {
25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET);
25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
25193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label next_map;
25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &next_map, Label::kNear);
25213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rbx, transitioned_maps->at(i), RelocInfo::EMBEDDED_OBJECT);
25223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
25233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&next_map);
25243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
252844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
2530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Return the generated code.
25323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
2533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
25363ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
25373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> object,
25383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> last) {
25399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
25409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
25419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
25429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
25439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
25449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
25457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that receiver is not a smi.
25479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(rax, &miss);
25487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check the maps of the full prototype chain. Also check that
25509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // global property cells up to (but not including) the last object
25519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // in the prototype chain are empty.
25529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss);
25539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If the last object in the prototype chain is a global object,
25559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // check that the global property cell is empty.
25569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (last->IsGlobalObject()) {
25573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateCheckPropertyCell(
25583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm(), Handle<GlobalObject>::cast(last), name, rdx, &miss);
25597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
25607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return undefined if maps of the full prototype chain are still the
25629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // same and no global property with this name contains a value.
25639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
25649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(0);
25659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
25679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
25689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
25703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NONEXISTENT, factory()->empty_string());
25719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
25729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25743ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
25753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
25769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                int index,
25773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
25789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
25799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
25809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
25819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
25829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
25839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
25849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadField(object, holder, rax, rbx, rdx, rdi, index, name, &miss);
25869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
25879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
25889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
25909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(FIELD, name);
25919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
25929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25943ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback(
25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
25963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
25999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
26009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
26019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
26029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
26039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
26049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
26053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(object, holder, rax, rcx, rdx, rbx, rdi, callback,
26063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       name, &miss);
26079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
26089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
26099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
26119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CALLBACKS, name);
26129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
26139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26153ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
26163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
26173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> value,
26183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name) {
26199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
26209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
26219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
26229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
26239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
26249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
26259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss);
26279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
26289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
26299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
26319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CONSTANT_FUNCTION, name);
26329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
26339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26353ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver,
26363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
26373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
26389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
26399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
26409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
26419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
26429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
26439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
26443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
26459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  LookupPostInterceptor(holder, name, &lookup);
26469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // TODO(368): Compile in the whole chain: all the interceptors in
26489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // prototypes and ultimate answer.
26493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(receiver, holder, &lookup, rax, rcx, rdx, rbx, rdi,
26503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          name, &miss);
26519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
26529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
26539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
26559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(INTERCEPTOR, name);
26569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
26579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal(
26603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
26613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
26623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
26643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_dont_delete) {
26659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
26669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
26679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
26689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
26699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
26709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
26719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the maps haven't changed.
26733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(rax, &miss);
26749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  CheckPrototypes(object, rax, holder, rbx, rdx, rdi, name, &miss);
26759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the value from the cell.
26773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rbx, cell);
26789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
26799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check for deleted property if property can actually be deleted.
26819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (!is_dont_delete) {
26829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
26839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ j(equal, &miss);
26849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else if (FLAG_debug_code) {
26859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
26869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ Check(not_equal, "DontDelete cells can't contain the hole");
26879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
26889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
268944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
269044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub(), 1);
26919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rax, rbx);
26929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(0);
26939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
269544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub_miss(), 1);
26969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
26977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
26989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
26999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(NORMAL, name);
27009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
27017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
27043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> receiver,
27053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> holder,
27069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                     int index) {
27079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
27089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax     : key
27099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx     : receiver
27109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
27119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
27129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
27137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
271444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
271544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_field(), 1);
27167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
27183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
27199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
27207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadField(receiver, holder, rdx, rbx, rcx, rdi, index, name, &miss);
27227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
272444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_field(), 1);
27259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
27267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
27289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(FIELD, name);
27299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
27307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27323ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback(
27333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
27353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
27363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
27379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
27389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax     : key
27399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx     : receiver
27409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
27419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
27429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
274344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
274444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_callback(), 1);
2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
27489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx, rdi, callback,
27513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       name, &miss);
27529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
275344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_callback(), 1);
27549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2755bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
27569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
27579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CALLBACKS, name);
27589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
27598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2760bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant(
27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
27633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> value) {
27669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
27679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
27689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
27699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
27709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
27719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
2772bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
277344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
277444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_constant_function(), 1);
2775bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
27769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
27773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
27789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
27798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
27809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadConstant(receiver, holder, rdx, rbx, rcx, rdi,
27819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                       value, name, &miss);
27829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
278344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_constant_function(), 1);
27849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
27858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
27869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
27879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CONSTANT_FUNCTION, name);
27889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
27898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
27908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
27913ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
27923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
27933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
27943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
27959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
27969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
27979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
27989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
27999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
28009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
280144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
280244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_interceptor(), 1);
28038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
28049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
28069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
28079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
28099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  LookupPostInterceptor(holder, name, &lookup);
28103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(receiver, holder, &lookup, rdx, rax, rcx, rbx, rdi,
28113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          name, &miss);
28129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
281344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_interceptor(), 1);
28149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
28159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
28169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
28179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(INTERCEPTOR, name);
2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28213ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
28223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
28239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
28249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
28259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
28269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
28279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
28289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
28293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
283044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
283144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_array_length(), 1);
28323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
28343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
28359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
28363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadArrayLength(masm(), rdx, rcx, &miss);
28389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
283944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_array_length(), 1);
28409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
28413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
28439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CALLBACKS, name);
28449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
28453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28473ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
28483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
28499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
28509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
28519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
28529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
28539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
28549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
28553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
285644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
285744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_string_length(), 1);
28583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
28603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
28619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
28623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss, true);
28649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
286544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_string_length(), 1);
28669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
28673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
28699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CALLBACKS, name);
28709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
28713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28733ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
28759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
28769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
28779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
28789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
28799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
28809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
28813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
288244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
288344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_function_prototype(), 1);
2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
28863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
28879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
28909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
289144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
28929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
28939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
28949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
28959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CALLBACKS, name);
2896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement(
29003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
29019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
29029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
29039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
290444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //  -- rsp[0] : return address
29059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
2906589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode();
29083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
2910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
2912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
29153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
2916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29193ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic(
29203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
29213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_ics) {
2922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : key
2924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
2925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0] : return address
2926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(rdx, &miss);
2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register map_reg = rbx;
2931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset));
2932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int receiver_count = receiver_maps->length();
2933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int current = 0; current < receiver_count; ++current) {
2934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check map and tail call if there's a match
29353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Cmp(map_reg, receiver_maps->at(current));
29363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, handler_ics->at(current), RelocInfo::CODE_TARGET);
2937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
29389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
2939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __  bind(&miss);
29409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
29419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
29429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
29433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
2944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Specialized stub for constructing objects from functions which only have only
2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// simple assignments of the form this.x = ...; in their body.
29493ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub(
29503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function) {
2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax : argc
2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rdi : constructor
2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[4] : last argument
2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_stub_call;
2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use r8 for holding undefined which is used in several places below.
296044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(r8, factory()->undefined_value());
2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check to see whether there are any break points in the function code. If
2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // there are jump to the generic constructor stub which calls the actual
2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code for the function thereby hitting the break points.
2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kDebugInfoOffset));
2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmpq(rbx, r8);
2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &generic_stub_call);
2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map and verify that it is in fact a map.
2973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Will both indicate a NULL and a Smi.
297569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(rbx, &generic_stub_call);
2977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(rbx, MAP_TYPE, rcx);
2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &generic_stub_call);
2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cannot construct functions this way.
2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdi: constructor
2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rbx: initial map
2984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpInstanceType(rbx, JS_FUNCTION_TYPE);
2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Assert(not_equal, "Function constructed by construct stub.");
2986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Now allocate the JSObject in new space.
2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdi: constructor
2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rbx: initial map
2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movzxbq(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset));
2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ shl(rcx, Immediate(kPointerSizeLog2));
29933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AllocateInNewSpace(rcx, rdx, rcx, no_reg,
29943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &generic_stub_call, NO_ALLOCATION_FLAGS);
2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSObject, now initialize the fields and add the heap tag.
2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rbx: initial map
2998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdx: JSObject (untagged)
2999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(Operand(rdx, JSObject::kMapOffset), rbx);
300044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(rbx, factory()->empty_fixed_array());
3001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(Operand(rdx, JSObject::kPropertiesOffset), rbx);
3002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(Operand(rdx, JSObject::kElementsOffset), rbx);
3003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: argc
3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdx: JSObject (untagged)
3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the address of the first in-object property into r9.
3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(r9, Operand(rdx, JSObject::kHeaderSize));
3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the first argument. The stack contains only the
3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // return address on top of the argc arguments.
3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(rcx, Operand(rsp, rax, times_pointer_size, 0));
3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: argc
3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rcx: first argument
3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdx: JSObject (untagged)
3015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r8: undefined
3016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r9: first in-object property of the JSObject
3017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the initialized properties with a constant value or a passed argument
3018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // depending on the this.x = ...; assignment in the function.
30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<SharedFunctionInfo> shared(function->shared());
3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
3021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (shared->IsThisPropertyAssignmentArgument(i)) {
3022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check if the argument assigned to the property is actually passed.
3023e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // If argument is not passed the property is set to undefined,
3024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // otherwise find it on the stack.
3025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int arg_number = shared->GetThisPropertyAssignmentArgument(i);
3026e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ movq(rbx, r8);
3027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmpq(rax, Immediate(arg_number));
3028e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ cmovq(above, rbx, Operand(rcx, arg_number * -kPointerSize));
3029e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Store value in the property.
3030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ movq(Operand(r9, i * kPointerSize), rbx);
3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
3032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to the constant value.
3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
3034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ Move(Operand(r9, i * kPointerSize), constant);
3035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the unused in-object property fields with undefined.
30398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(function->has_initial_map());
3040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = shared->this_property_assignments_count();
30418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang       i < function->initial_map()->inobject_properties();
3042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       i++) {
3043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(Operand(r9, i * kPointerSize), r8);
3044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: argc
3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdx: JSObject (untagged)
3048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move argc to rbx and the JSObject to return to rax and tag it.
3049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rbx, rax);
3050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rax, rdx);
3051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ or_(rax, Immediate(kHeapObjectTag));
3052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: JSObject
3054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rbx: argc
3055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack and return.
3056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(rcx);
3057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(rsp, Operand(rsp, rbx, times_pointer_size, 1 * kPointerSize));
3058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rcx);
305944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
306044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects(), 1);
306144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects_stub(), 1);
3062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
3063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic stub in case the specialized code cannot handle the
3065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // construction.
3066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_stub_call);
30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code = isolate()->builtins()->JSConstructStubGeneric();
30683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(code, RelocInfo::CODE_TARGET);
3069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode();
3072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __
30763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm)
30773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
30783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
30793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
30803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
30811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
30821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rax    : key
30831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rdx    : receiver
30841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rsp[0] : return address
30851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
30863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, miss_force_generic;
3087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
30883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
30893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
30901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
30913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(rax, &miss_force_generic);
30923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger32(rbx, rax);
30933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
30941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
30953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check whether the elements is a number dictionary.
30963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rdx: receiver
30973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rax: key
30983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rbx: key as untagged int32
30993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rcx: elements
31003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax);
31013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
31023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
31033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
3104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
31053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rax    : key
3106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
31073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rsp[0]  : return address
3108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
31093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
31103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
31113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
3112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
31133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
31143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
31153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rax    : key
31163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rdx    : receiver
31173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rsp[0]  : return address
31183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
31193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_ic =
31203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
31213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray(
3125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3126589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : key
3129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
3130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0] : return address
3131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label slow, miss_force_generic;
3133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
3136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
3138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(rax, &miss_force_generic);
31391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
31401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the index is in range.
3141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
31421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ SmiToInteger32(rcx, rax);
314369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmpq(rax, FieldOperand(rbx, ExternalArray::kLengthOffset));
31441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
3145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &miss_force_generic);
31461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
31471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rax: index (as a smi)
31481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rdx: receiver (JSObject)
31491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rcx: untagged index
31501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rbx: elements array
31511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
31521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rbx: base pointer of external storage
31533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3154589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
31551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
31561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3157589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
3158589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
31591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0));
31601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3161589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
31621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0));
31631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
31651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0));
31661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3167589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
31681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0));
31691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3170589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
31711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movl(rcx, Operand(rbx, rcx, times_4, 0));
31721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3173589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
31741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0));
31751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3176589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
3177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ movsd(xmm0, Operand(rbx, rcx, times_8, 0));
3178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
31791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    default:
31801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
31811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
31821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
31831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
31841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rax: index
31851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rdx: receiver
31861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For integer array types:
31871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rcx: value
31881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For floating-point array type:
31891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // xmm0: value as double.
31901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
31911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(kSmiValueSize == 32);
3192589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
31931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the UnsignedInt array type, we need to see whether
31941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // the value can be represented in a Smi. If not, we need to convert
31951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // it to a HeapNumber.
3196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label box_int;
31971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfUIntNotValidSmiValue(rcx, &box_int, Label::kNear);
31991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Integer32ToSmi(rax, rcx);
32011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
32021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&box_int);
32041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Allocate a HeapNumber for the int and perform int-to-double
32061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // conversion.
32071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // The value is zero-extended since we loaded the value from memory
32081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // with movl.
32091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cvtqsi2sd(xmm0, rcx);
32101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ AllocateHeapNumber(rcx, rbx, &slow);
32121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Set the value.
32131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
32141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ movq(rax, rcx);
32151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
3216589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
3217589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch             elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
32181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the floating-point array type, we need to always allocate a
32191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // HeapNumber.
32201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ AllocateHeapNumber(rcx, rbx, &slow);
32211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Set the value.
32221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
32231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ movq(rax, rcx);
32241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
32251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
32261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Integer32ToSmi(rax, rcx);
32271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
32281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
32291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Slow case: Jump to runtime.
32311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
3232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm->isolate()->counters();
323344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
32341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
32361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rax    : key
32371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rdx    : receiver
32381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rsp[0]  : return address
32391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
32401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
32431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Miss case: Jump to runtime.
3245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
32461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : key
3249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
3250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0]  : return address
3251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
3253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
32551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
32561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray(
3259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3260589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
32611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
32621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rax     : value
32631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rcx     : key
32641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rdx     : receiver
32651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rsp[0]  : return address
32661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
3267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label slow, miss_force_generic;
32681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
327144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
327244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the key is a smi.
3273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(rcx, &miss_force_generic);
32741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the index is in range.
3276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
32771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ SmiToInteger32(rdi, rcx);  // Untag the index.
327869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmpq(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset));
32791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
3280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &miss_force_generic);
32811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Handle both smis and HeapNumbers in the fast path. Go to the
32831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // runtime for all other kinds of values.
32841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rax: value
32851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rcx: key (a smi)
32861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rdx: receiver (a JSObject)
32871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rbx: elements array
32881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rdi: untagged key
3289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label check_heap_number;
3290589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
329144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Float to pixel conversion is only implemented in the runtime for now.
329244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ JumpIfNotSmi(rax, &slow);
329344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
3294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfNotSmi(rax, &check_heap_number, Label::kNear);
329544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
32961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // No more branches to slow case on this path.  Key and receiver not needed.
32971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ SmiToInteger32(rdx, rax);
32981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
32991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rbx: base pointer of external storage
33003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3301589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
330244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      {  // Clamp the value to [0..255].
3303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Label done;
330444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ testl(rdx, Immediate(0xFFFFFF00));
3305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(zero, &done, Label::kNear);
330644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ setcc(negative, rdx);  // 1 if negative, 0 if positive.
330744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ decb(rdx);  // 0 if negative, 255 if positive.
330844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ bind(&done);
330944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
331044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ movb(Operand(rbx, rdi, times_1, 0), rdx);
331144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
3312589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
3313589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
33141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movb(Operand(rbx, rdi, times_1, 0), rdx);
33151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3316589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
3317589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
33181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movw(Operand(rbx, rdi, times_2, 0), rdx);
33191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3320589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
3321589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
33221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movl(Operand(rbx, rdi, times_4, 0), rdx);
33231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3324589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
33251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Need to perform int-to-float conversion.
33261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ cvtlsi2ss(xmm0, rdx);
33271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
33281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3329589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
3330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Need to perform int-to-float conversion.
3331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ cvtlsi2sd(xmm0, rdx);
3332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ movsd(Operand(rbx, rdi, times_8, 0), xmm0);
3333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_ELEMENTS:
33353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case FAST_SMI_ONLY_ELEMENTS:
3336589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_DOUBLE_ELEMENTS:
3337589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case DICTIONARY_ELEMENTS:
3338589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case NON_STRICT_ARGUMENTS_ELEMENTS:
33391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
33401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
33411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
33421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ret(0);
33431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
334444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // TODO(danno): handle heap number -> pixel array conversion
3345589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
334644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ bind(&check_heap_number);
334744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // rax: value
334844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // rcx: key (a smi)
334944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // rdx: receiver (a JSObject)
335044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // rbx: elements array
335144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // rdi: untagged key
335244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister);
335344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ j(not_equal, &slow);
335444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // No more branches to slow case on this path.
335544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
335644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The WebGL specification leaves the behavior of storing NaN and
335744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // +/-Infinity into integer arrays basically undefined. For more
335844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // reproducible behavior, convert these to zero.
335944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
336044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
33611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // rdi: untagged index
33621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // rbx: base pointer of external storage
336344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // top of FPU stack: value
3364589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
336544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ cvtsd2ss(xmm0, xmm0);
336644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
336744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ ret(0);
3368589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ movsd(Operand(rbx, rdi, times_8, 0), xmm0);
3370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ ret(0);
337144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
337244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Perform float-to-int conversion with truncation (round-to-zero)
337344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // behavior.
337444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
337544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Convert to int32 and store the low byte/word.
337644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // If the value is NaN or +/-infinity, the result is 0x80000000,
337744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // which is automatically zero when taken mod 2^n, n < 32.
337844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // rdx: value (converted to an untagged integer)
337944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // rdi: untagged index
338044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // rbx: base pointer of external storage
33813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      switch (elements_kind) {
3382589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_BYTE_ELEMENTS:
3383589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
338444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          __ cvttsd2si(rdx, xmm0);
338544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          __ movb(Operand(rbx, rdi, times_1, 0), rdx);
338644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
3387589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_SHORT_ELEMENTS:
3388589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
338944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          __ cvttsd2si(rdx, xmm0);
339044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          __ movw(Operand(rbx, rdi, times_2, 0), rdx);
339144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
3392589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_INT_ELEMENTS:
3393589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_UNSIGNED_INT_ELEMENTS:
339444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          // Convert to int64, so that NaN and infinities become
339544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          // 0x8000000000000000, which is zero mod 2^32.
339644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          __ cvttsd2siq(rdx, xmm0);
339744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          __ movl(Operand(rbx, rdi, times_4, 0), rdx);
339844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
3399589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_PIXEL_ELEMENTS:
3400589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_FLOAT_ELEMENTS:
3401589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_DOUBLE_ELEMENTS:
3402589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case FAST_ELEMENTS:
34033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        case FAST_SMI_ONLY_ELEMENTS:
3404589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case FAST_DOUBLE_ELEMENTS:
3405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case DICTIONARY_ELEMENTS:
3406589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case NON_STRICT_ARGUMENTS_ELEMENTS:
340744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          UNREACHABLE();
340844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
341044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ ret(0);
34111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
34121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
34131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Slow case: call runtime.
34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
34161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rax     : value
34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rcx     : key
34201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rdx     : receiver
34211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rsp[0]  : return address
34221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
34231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
3426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Miss case: call runtime.
3428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : value
3432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rcx    : key
3433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
3434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0] : return address
3435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
3438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : key
3446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
3447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0] : return address
3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic;
34501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
34531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
3455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(rax, &miss_force_generic);
3456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array.
3458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
3459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AssertFastElements(rcx);
3460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is within bounds.
3462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
3463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &miss_force_generic);
3464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the result and make sure it's not the hole.
3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2);
3467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(rbx, FieldOperand(rcx,
3468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            index.reg,
3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            index.scale,
3470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            FixedArray::kHeaderSize));
3471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
3472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &miss_force_generic);
3473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(rax, rbx);
3474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
3475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Code* code = masm->isolate()->builtins()->builtin(
3478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Builtins::kKeyedLoadIC_MissForceGeneric);
3479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic(code);
3480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
3481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
34843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
34853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
34863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
34873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rax    : key
34883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rdx    : receiver
34893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rsp[0] : return address
34903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
34913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label miss_force_generic, slow_allocate_heapnumber;
34923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
34933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
34943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
34953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
34963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a smi.
34973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(rax, &miss_force_generic);
34983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
34993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the elements array.
35003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
35013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AssertFastElements(rcx);
35023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is within bounds.
35043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
35053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(above_equal, &miss_force_generic);
35063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check for the hole
35083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger32(kScratchRegister, rax);
35093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
35103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmpl(FieldOperand(rcx, kScratchRegister, times_8, offset),
35113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          Immediate(kHoleNanUpper32));
35123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(equal, &miss_force_generic);
35133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Always allocate a heap number for the result.
35153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movsd(xmm0, FieldOperand(rcx, kScratchRegister, times_8,
35163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              FixedDoubleArray::kHeaderSize));
35173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber);
35183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Set the value.
35193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(rax, rcx);
35203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
35213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
35223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow_allocate_heapnumber);
35243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
35253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
35263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
35273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
35293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_ic =
35303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
35313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
35323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
35333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement(
35363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
35373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
35383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind elements_kind,
35393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
3540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : value
3542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rcx    : key
3543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
3544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0] : return address
3545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
35463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, transition_elements_kind, finish_store, grow;
35473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label check_capacity, slow;
3548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
3551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
3553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(rcx, &miss_force_generic);
3554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
35553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
35563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotSmi(rax, &transition_elements_kind);
35573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
35583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array and make sure it is a fast element array, not 'cow'.
3560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
3561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is within bounds.
3562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (is_js_array) {
3563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
35643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (grow_mode == ALLOW_JSARRAY_GROWTH) {
35653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(above_equal, &grow);
35663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
35673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(above_equal, &miss_force_generic);
35683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
3571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(above_equal, &miss_force_generic);
3572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
35743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset),
35753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 Heap::kFixedArrayMapRootIndex);
35763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &miss_force_generic);
35773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
35793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
35803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiToInteger32(rcx, rcx);
35813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
35823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            rax);
35833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
35843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Do the store and update the write barrier.
35853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(elements_kind == FAST_ELEMENTS);
35863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiToInteger32(rcx, rcx);
35873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lea(rcx,
35883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize));
35893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(Operand(rcx, 0), rax);
35903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure to preserve the value in register rax.
35913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(rbx, rax);
35923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWrite(rdi, rcx, rbx, kDontSaveFPRegs);
35933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Done.
3596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
3597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle store cache miss.
3599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic_force_generic =
3601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
36033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
36053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
36063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(ic_miss, RelocInfo::CODE_TARGET);
36073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
36093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array by a single element if possible.
36103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
36113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
36133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime. Flags are already set by previous
36143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // compare.
36153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &miss_force_generic);
36163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
36183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
36193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
36203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(rdi, Heap::kEmptyFixedArrayRootIndex);
36213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &check_capacity);
36223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
36243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, rdi, rbx, r8, &slow, TAG_OBJECT);
36253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rax: value
36273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rcx: key
36283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdx: receiver
36293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdi: elements
36303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
36313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(FieldOperand(rdi, JSObject::kMapOffset),
36323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            masm->isolate()->factory()->fixed_array_map());
36333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(FieldOperand(rdi, FixedArray::kLengthOffset),
36343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Smi::FromInt(JSArray::kPreallocatedArrayElements));
36353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(rbx, Heap::kTheHoleValueRootIndex);
36363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
36373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(FieldOperand(rdi, FixedArray::SizeFor(i)), rbx);
36383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
36393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Store the element at index zero.
36413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(FieldOperand(rdi, FixedArray::SizeFor(0)), rax);
36423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
36443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rdi);
36453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(rdx, JSObject::kElementsOffset, rdi, rbx,
36463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
36473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
36493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(FieldOperand(rdx, JSArray::kLengthOffset), Smi::FromInt(1));
36503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ret(0);
36513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
36533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for cow elements, in general they are not handled by this stub.
36543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset),
36553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Heap::kFixedCOWArrayMapRootIndex);
36563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, &miss_force_generic);
36573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rax: value
36593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rcx: key
36603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdx: receiver
36613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdi: elements
36623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
36633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmpq(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
36643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &slow);
36653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
36673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset),
36683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Smi::FromInt(1));
36693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
36703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
36723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(ic_slow, RelocInfo::CODE_TARGET);
36743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
36751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
36761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
36783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
36793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm,
36803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
36813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
36823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
36833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rax    : value
36843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rcx    : key
36853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rdx    : receiver
36863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rsp[0] : return address
36873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
36883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, transition_elements_kind, finish_store;
36893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label grow, slow, check_capacity;
36903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
36923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
36933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a smi.
36953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(rcx, &miss_force_generic);
36963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the elements array.
36983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
36993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AssertFastElements(rdi);
37003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is within bounds.
37023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (is_js_array) {
37033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
37043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (grow_mode == ALLOW_JSARRAY_GROWTH) {
37053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ j(above_equal, &grow);
37063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
37073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ j(above_equal, &miss_force_generic);
37083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
37093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
37103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ SmiCompare(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset));
37113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &miss_force_generic);
37123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
37133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Handle smi values specially
37153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
37163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger32(rcx, rcx);
37173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0,
37183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 &transition_elements_kind);
37193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
37203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Handle store cache miss, replacing the ic with the generic stub.
37223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
37233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> ic_force_generic =
37243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
37253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
37263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
37283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Restore smi-tagging of rcx.
37293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Integer32ToSmi(rcx, rcx);
37303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
37313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(ic_miss, RelocInfo::CODE_TARGET);
37323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
37343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array by a single element if possible.
37353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
37363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
37383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime. Flags are already set by previous
37393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // compare.
37403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &miss_force_generic);
37413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Transition on values that can't be stored in a FixedDoubleArray.
37433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label value_is_smi;
37443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(rax, &value_is_smi);
37453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
37463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Heap::kHeapNumberMapRootIndex);
37473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &transition_elements_kind);
37483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&value_is_smi);
37493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
37513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
37523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
37533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(rdi, Heap::kEmptyFixedArrayRootIndex);
37543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &check_capacity);
37553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
37573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, rdi, rbx, r8, &slow, TAG_OBJECT);
37583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rax: value
37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rcx: key
37613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdx: receiver
37623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdi: elements
37633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Initialize the new FixedDoubleArray. Leave elements unitialized for
37643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // efficiency, they are guaranteed to be initialized before use.
37653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(FieldOperand(rdi, JSObject::kMapOffset),
37663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            masm->isolate()->factory()->fixed_double_array_map());
37673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(FieldOperand(rdi, FixedDoubleArray::kLengthOffset),
37683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Smi::FromInt(JSArray::kPreallocatedArrayElements));
37693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
37713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rdi);
37723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(rdx, JSObject::kElementsOffset, rdi, rbx,
37733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
37743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
37763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(FieldOperand(rdx, JSArray::kLengthOffset), Smi::FromInt(1));
37779413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch    __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
37783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
37793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
37813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rax: value
37823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rcx: key
37833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdx: receiver
37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdi: elements
37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
37863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmpq(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset));
37873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &slow);
37883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
37903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset),
37913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Smi::FromInt(1));
37923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
37933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
37953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
37963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(ic_slow, RelocInfo::CODE_TARGET);
37973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
37983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
37993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
3802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
3804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
3806