stub-cache-x64.cc revision 9413bcbe2192ed4d701281130490e0ba336debdc
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
11079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Save necessary data before invoking an interceptor.
11089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Requires a frame to make GC aware of pushed pointers.
11093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FrameScope frame_scope(masm(), StackFrame::INTERNAL);
11116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // CALLBACKS case needs a receiver to be passed into C++ callback.
11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ push(receiver);
11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(holder_reg);
11173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(name_reg);
1118592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
11193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Invoke an interceptor.  Note: map checks from receiver to
11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // interceptor's holder has been compiled before (see a caller
11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // of this method.)
11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCallLoadPropertyWithInterceptor(masm(),
11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             receiver,
11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder_reg,
11253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             name_reg,
11263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             interceptor_holder);
11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if interceptor provided a value for property.  If it's
11293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the case, return immediately.
11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label interceptor_failed;
11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(equal, &interceptor_failed);
11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      frame_scope.GenerateLeaveFrame();
11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ret(0);
11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&interceptor_failed);
11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(name_reg);
11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(holder_reg);
11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ pop(receiver);
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
11426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Leave the internal frame.
11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
114585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
11469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Check that the maps from interceptor's holder to lookup's holder
11479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // haven't changed.  And load lookup's holder into |holder| register.
11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (*interceptor_holder != lookup->holder()) {
11499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      holder_reg = CheckPrototypes(interceptor_holder,
11509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                   holder_reg,
11513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Handle<JSObject>(lookup->holder()),
11529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                   scratch1,
11539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                   scratch2,
11549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                   scratch3,
11559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                   name,
11569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                   miss);
11579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
11586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (lookup->type() == FIELD) {
11609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // We found FIELD property in prototype chain of interceptor's holder.
11619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Retrieve a field from field's holder.
11629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      GenerateFastPropertyLoad(masm(), rax, holder_reg,
11633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Handle<JSObject>(lookup->holder()),
11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               lookup->GetFieldIndex());
11659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ ret(0);
11669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    } else {
11679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // We found CALLBACKS property in prototype chain of interceptor's
11689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // holder.
11699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ASSERT(lookup->type() == CALLBACKS);
11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<AccessorInfo> callback(
11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject()));
11729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ASSERT(callback->getter() != NULL);
1173756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
11749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Tail call to runtime.
11759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Important invariant in CALLBACKS case: the code above must be
11769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // structured to never clobber |receiver| register.
11779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ pop(scratch2);  // return address
11789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ push(receiver);
11799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ push(holder_reg);
11803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Move(holder_reg, callback);
11819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
11829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ push(holder_reg);
11839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ push(name_reg);
11849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ push(scratch2);  // restore return address
1185756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
11869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ExternalReference ref =
118744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
118844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            isolate());
11899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ TailCallExternalReference(ref, 5, 1);
11906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
11919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {  // !compile_followup_inline
11929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Call the runtime system to load the interceptor.
11939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Check that the maps haven't changed.
11949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
11959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                          scratch1, scratch2, scratch3,
11969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                          name, miss);
11979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ pop(scratch2);  // save old return address
11989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    PushInterceptorArguments(masm(), receiver, holder_reg,
11999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                             name_reg, interceptor_holder);
12009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ push(scratch2);  // restore old return address
12016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    ExternalReference ref = ExternalReference(
120344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate());
12049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ TailCallExternalReference(ref, 5, 1);
12055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
12066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
12109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (kind_ == Code::KEYED_CALL_IC) {
12113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Cmp(rcx, name);
12129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ j(not_equal, miss);
12139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
12149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
12183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
12193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
12209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                   Label* miss) {
12219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(holder->IsGlobalObject());
12226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the number of arguments.
12249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
12259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
12266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack.
12276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
12286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the maps haven't changed.
12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(rdx, miss);
12329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss);
12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell(
12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* miss) {
12409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the value from the cell.
12413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rdi, cell);
12429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset));
124380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
12449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the cell contains the same function.
12453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (heap()->InNewSpace(*function)) {
12469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // We can't embed a pointer to a function in new space so we have
12479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // to verify that the shared function info is unchanged. This has
12489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // the nice side effect that multiple closures based on the same
12499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // function can all use this call IC. Before we load through the
12509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // function, we have to verify that it still is a function.
12519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ JumpIfSmi(rdi, miss);
12529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax);
12539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ j(not_equal, miss);
125480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
12559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Check the shared function info. Make sure it hasn't changed.
12569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ Move(rax, Handle<SharedFunctionInfo>(function->shared()));
12579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax);
125880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Cmp(rdi, function);
126080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, miss);
12629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
126380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
126480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() {
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code =
1267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                               kind_,
12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               extra_state_);
12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(code, RelocInfo::CODE_TARGET);
12717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
12727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
12769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                int index,
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
127880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ----------- S t a t e -------------
12799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rcx                 : function name
12809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[0]              : return address
12819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[8]              : argument argc
12829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[16]             : argument argc - 1
12839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ...
12849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[argc * 8]       : argument 1
12859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[(argc + 1) * 8] : argument 0 = receiver
128680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // -----------------------------------
128780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label miss;
12889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
128980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateNameCheck(name, &miss);
129080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
12919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the receiver from the stack.
12929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
12939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
129480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
12959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the receiver isn't a smi.
12969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(rdx, &miss);
129780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
12989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Do the right check and compute the holder register.
12999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi,
13009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                 name, &miss);
130180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
13029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateFastPropertyLoad(masm(), rdi, reg, holder, index);
130380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
13049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the function really is a function.
13059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(rdi, &miss);
13069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx);
13079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
13089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
13099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Patch the receiver on the stack with the global proxy if
13109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // necessary.
13119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (object->IsGlobalObject()) {
13129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
13139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
13149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
13159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
13169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Invoke the function.
13173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
1319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
1320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
1321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
13227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Handle call cache miss.
132480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&miss);
13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
132680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
132780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Return the generated code.
13289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(FIELD, name);
132980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
13306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13323ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall(
13333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
13343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
13373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
133859151504615d929945dc59db37bf1166937748c6Steve Block  // ----------- S t a t e -------------
13399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx                 : name
134059151504615d929945dc59db37bf1166937748c6Steve Block  //  -- rsp[0]              : return address
134159151504615d929945dc59db37bf1166937748c6Steve Block  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
134259151504615d929945dc59db37bf1166937748c6Steve Block  //  -- ...
134359151504615d929945dc59db37bf1166937748c6Steve Block  //  -- rsp[(argc + 1) * 8] : receiver
134459151504615d929945dc59db37bf1166937748c6Steve Block  // -----------------------------------
134559151504615d929945dc59db37bf1166937748c6Steve Block
13469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If object is not an array, bail out to regular call.
13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
134859151504615d929945dc59db37bf1166937748c6Steve Block
134959151504615d929945dc59db37bf1166937748c6Steve Block  Label miss;
135059151504615d929945dc59db37bf1166937748c6Steve Block  GenerateNameCheck(name, &miss);
135159151504615d929945dc59db37bf1166937748c6Steve Block
13529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the receiver from the stack.
13539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
13549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
135559151504615d929945dc59db37bf1166937748c6Steve Block
13569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the receiver isn't a smi.
13579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(rdx, &miss);
135859151504615d929945dc59db37bf1166937748c6Steve Block
13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
13603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, &miss);
13619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
13629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (argc == 0) {
13639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Noop, return the length.
13649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
13659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ ret((argc + 1) * kPointerSize);
136659151504615d929945dc59db37bf1166937748c6Steve Block  } else {
13679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Label call_builtin;
136859151504615d929945dc59db37bf1166937748c6Steve Block
13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (argc == 1) {  // Otherwise fall through to call builtin.
13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label attempt_to_grow_elements, with_write_barrier;
137159151504615d929945dc59db37bf1166937748c6Steve Block
13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements array of the object.
13733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
13745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
13753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check that the elements are in fast mode and writable.
13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             factory()->fixed_array_map());
13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &call_builtin);
13795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
13809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Get the array's length into rax and calculate new length.
13819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
13829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
13839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ addl(rax, Immediate(argc));
138459151504615d929945dc59db37bf1166937748c6Steve Block
13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements' length into rcx.
13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
138759151504615d929945dc59db37bf1166937748c6Steve Block
13889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Check if we could survive without allocation.
13899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ cmpl(rax, rcx);
13909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ j(greater, &attempt_to_grow_elements);
13919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
13923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if value is a smi.
13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rcx, Operand(rsp, argc * kPointerSize));
13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfNotSmi(rcx, &with_write_barrier);
13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Save new length.
13979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
13989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(FieldOperand(rdi,
14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           rax,
14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           times_pointer_size,
14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           FixedArray::kHeaderSize - argc * kPointerSize),
14043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              rcx);
14059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ Integer32ToSmi(rax, rax);  // Return new length as smi.
140785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      __ ret((argc + 1) * kPointerSize);
14089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
140985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      __ bind(&with_write_barrier);
14109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_smi_only_arrays  && !FLAG_trace_elements_transitions) {
14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label fast_object, not_fast_object;
14153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(rbx, &not_fast_object, Label::kNear);
14163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&fast_object);
14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // In case of fast smi-only, convert to fast object, otherwise bail out.
14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&not_fast_object);
14193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastSmiOnlyElements(rbx, &call_builtin);
14203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // rdx: receiver
14213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // rbx: map
14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ movq(r9, rdi);  // Backup rdi as it is going to be trashed.
14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               FAST_ELEMENTS,
14253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               rbx,
14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               rdi,
14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               &call_builtin);
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm());
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ movq(rdi, r9);
14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&fast_object);
14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(rbx, &call_builtin);
14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Save new length.
14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lea(rdx, FieldOperand(rdi,
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               rax, times_pointer_size,
14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               FixedArray::kHeaderSize - argc * kPointerSize));
14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(Operand(rdx, 0), rcx);
1443592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWrite(rdi, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     OMIT_SMI_CHECK);
1446592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Integer32ToSmi(rax, rax);  // Return new length as smi.
14489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ ret((argc + 1) * kPointerSize);
14499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ bind(&attempt_to_grow_elements);
14519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      if (!FLAG_inline_new) {
14529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ jmp(&call_builtin);
14539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      }
14549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rbx, Operand(rsp, argc * kPointerSize));
14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Growing elements that are SMI-only requires special handling in case
14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the new element is non-Smi. For now, delegate to the builtin.
14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label no_fast_elements_check;
14593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfSmi(rbx, &no_fast_elements_check);
14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar);
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&no_fast_elements_check);
14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ExternalReference new_space_allocation_top =
146544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_top_address(isolate());
14669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ExternalReference new_space_allocation_limit =
146744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_limit_address(isolate());
14689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      const int kAllocationDelta = 4;
14709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Load top.
147144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ Load(rcx, new_space_allocation_top);
14729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Check if it's the end of elements.
14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lea(rdx, FieldOperand(rdi,
14759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                               rax, times_pointer_size,
14769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                               FixedArray::kHeaderSize - argc * kPointerSize));
14779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ cmpq(rdx, rcx);
14789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ j(not_equal, &call_builtin);
14799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ addq(rcx, Immediate(kAllocationDelta * kPointerSize));
148044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Operand limit_operand =
148144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          masm()->ExternalOperand(new_space_allocation_limit);
148244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ cmpq(rcx, limit_operand);
14839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ j(above, &call_builtin);
14849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // We fit and could grow elements.
148644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ Store(new_space_allocation_top, rcx);
14879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Push the argument...
14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(Operand(rdx, 0), rbx);
14909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // ... and fill the rest with holes.
14919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
14929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      for (int i = 1; i < kAllocationDelta; i++) {
14939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ movq(Operand(rdx, i * kPointerSize), kScratchRegister);
14949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      }
14959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // We know the elements array is in new space so we don't need the
14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // remembered set, but we just pushed a value onto it so we may have to
14983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // tell the incremental marker to rescan the object that we just grew.  We
14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // don't need to worry about the holes because they are in old space and
15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // already marked black.
15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Restore receiver to rdx as finish sequence assumes it's here.
15049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
15059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
15069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Increment element's and array's sizes.
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset),
15089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                        Smi::FromInt(kAllocationDelta));
15099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
15109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Make new length a smi before returning it.
15119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ Integer32ToSmi(rax, rax);
15129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax);
15139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
15149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      __ ret((argc + 1) * kPointerSize);
15159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
15169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
15179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ bind(&call_builtin);
151844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
151944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   isolate()),
15209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                 argc + 1,
15219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                 1);
15229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
152359151504615d929945dc59db37bf1166937748c6Steve Block
152459151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&miss);
15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
152659151504615d929945dc59db37bf1166937748c6Steve Block
152759151504615d929945dc59db37bf1166937748c6Steve Block  // Return the generated code.
15289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(function);
15290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
15300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
15310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall(
15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1538f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // ----------- S t a t e -------------
15399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx                 : name
1540f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- rsp[0]              : return address
1541f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1542f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- ...
1543f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- rsp[(argc + 1) * 8] : receiver
1544f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // -----------------------------------
1545f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If object is not an array, bail out to regular call.
15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
1548f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss, return_undefined, call_builtin;
1550f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  GenerateNameCheck(name, &miss);
1551f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the receiver from the stack.
15539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
15549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1555f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the receiver isn't a smi.
15579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(rdx, &miss);
1558f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, &miss);
1561f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the elements array of the object.
15639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
1564f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the elements are in fast mode and writable.
15669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
15679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                 Heap::kFixedArrayMapRootIndex);
15689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &call_builtin);
1569f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the array's length into rcx and calculate new length.
15719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
15729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ subl(rcx, Immediate(1));
15739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(negative, &return_undefined);
1574f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the last element.
15769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ LoadRoot(r9, Heap::kTheHoleValueRootIndex);
15779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rax, FieldOperand(rbx,
15789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                            rcx, times_pointer_size,
15799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                            FixedArray::kHeaderSize));
15809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check if element is already the hole.
15819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ cmpq(rax, r9);
15829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If so, call slow-case to also check prototypes for value.
15839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(equal, &call_builtin);
1584f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Set the array's length.
15869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
1587f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Fill with the hole and return original value.
15899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(FieldOperand(rbx,
15909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                       rcx, times_pointer_size,
15919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                       FixedArray::kHeaderSize),
15929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block          r9);
15939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret((argc + 1) * kPointerSize);
1594f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&return_undefined);
15969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
15979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret((argc + 1) * kPointerSize);
1598f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
15999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&call_builtin);
160044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ TailCallExternalReference(
160144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(Builtins::c_ArrayPop, isolate()),
160244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      argc + 1,
160344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      1);
1604f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1605f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&miss);
16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1607f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1608f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Return the generated code.
16099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(function);
1610f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
1611f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1612f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
16153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
16173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
16209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx                 : function name
16219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]              : return address
16229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
16239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- ...
16249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc + 1) * 8] : receiver
1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If object is not a string, bail out to regular call.
16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
16299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
1633b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
16349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label index_out_of_range;
1635b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
1636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
16373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1639b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1640b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1641b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the maps starting from the prototype haven't changed.
16449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateDirectLoadGlobalFunctionPrototype(masm(),
16459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                            Context::STRING_FUNCTION_INDEX,
16469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                            rax,
16479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                            &miss);
16483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
16503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  rax, holder, rbx, rdx, rdi, name, &miss);
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register receiver = rbx;
16539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register index = rdi;
16549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register result = rax;
16559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
16569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (argc > 0) {
16579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(index, Operand(rsp, (argc - 0) * kPointerSize));
16589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
16599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
16609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharCodeAtGenerator generator(receiver,
16633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index,
16643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      result,
16653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a string.
16663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a number.
16673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index_out_of_range_label,
16683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      STRING_INDEX_IS_NUMBER);
16693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
16709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret((argc + 1) * kPointerSize);
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  StubRuntimeCallHelper call_helper;
16733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1675b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1676b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
1677b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ LoadRoot(rax, Heap::kNanValueRootIndex);
1678b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ ret((argc + 1) * kPointerSize);
1679b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1682b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in rcx.
16833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rcx, name);
1684b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
16853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
16889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(function);
1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16923ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall(
16933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
16943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
16953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
16963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
16973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
16999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx                 : function name
17009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]              : return address
17019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
17029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- ...
17039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc + 1) * 8] : receiver
170459151504615d929945dc59db37bf1166937748c6Steve Block  // -----------------------------------
170559151504615d929945dc59db37bf1166937748c6Steve Block
17069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If object is not a string, bail out to regular call.
17073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
17089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
17099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1711b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
17129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label index_out_of_range;
1713b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
17153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1717b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1718b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1719b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
17209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
17219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the maps starting from the prototype haven't changed.
17229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateDirectLoadGlobalFunctionPrototype(masm(),
17239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                            Context::STRING_FUNCTION_INDEX,
17249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                            rax,
17259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                            &miss);
17263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
17273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
17283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  rax, holder, rbx, rdx, rdi, name, &miss);
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register receiver = rax;
17319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register index = rdi;
17323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = rdx;
17339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register result = rax;
17349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
17359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (argc > 0) {
17369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(index, Operand(rsp, (argc - 0) * kPointerSize));
17379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
17389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharAtGenerator generator(receiver,
17423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index,
17433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  scratch,
17443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  result,
17453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a string.
17463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a number.
17473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index_out_of_range_label,
17483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  STRING_INDEX_IS_NUMBER);
17493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
17509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret((argc + 1) * kPointerSize);
17519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
17529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  StubRuntimeCallHelper call_helper;
17533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1755b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1756b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
1757b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ LoadRoot(rax, Heap::kEmptyStringRootIndex);
1758b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ ret((argc + 1) * kPointerSize);
1759b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1761b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in rcx.
17623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rcx, name);
1763b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
17643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
17679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(function);
1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
17733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
17743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
17763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
17789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx                 : function name
17799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]              : return address
17809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
17819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- ...
17829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc + 1) * 8] : receiver
1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If the object is not a JSObject or we got an unexpected number of
17869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // arguments, bail out to the regular call.
17873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int argc = arguments().immediate();
17883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
17919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateNameCheck(name, &miss);
1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
17949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rdx, Operand(rsp, 2 * kPointerSize));
17959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ JumpIfSmi(rdx, &miss);
17963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
17973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
17989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
17993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
18003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
18013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
18029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    GenerateLoadFunctionFromCell(cell, function, &miss);
18039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Load the char code argument.
18069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Register code = rbx;
18079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(code, Operand(rsp, 1 * kPointerSize));
18086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check the code is a smi.
18109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label slow;
18119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfNotSmi(code, &slow);
18126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Convert the smi code to uint16.
18149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ SmiAndConstant(code, code, Smi::FromInt(0xffff));
18156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharFromCodeGenerator generator(code, rax);
18173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
18189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(2 * kPointerSize);
18196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  StubRuntimeCallHelper call_helper;
18213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
18229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
18239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Tail call the full function. We do not have to patch the receiver
18249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // because the function makes no use of it.
18259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&slow);
18263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
1828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
1829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
1830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
18316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
18339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rcx: function name.
18343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
18356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
18373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
18386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
18396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18413ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall(
18423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
18433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
18443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
18453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
18463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
18479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // TODO(872): implement this.
18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return Handle<Code>::null();
1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18523ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall(
18533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
18543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
18563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
18573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
18599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx                 : function name
18609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]              : return address
18619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
18629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- ...
18639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[(argc + 1) * 8] : receiver
1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
18659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
18669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If the object is not a JSObject or we got an unexpected number of
18679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // arguments, bail out to the regular call.
18683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int argc = arguments().immediate();
18693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
18709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
18729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateNameCheck(name, &miss);
1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
18759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rdx, Operand(rsp, 2 * kPointerSize));
18769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ JumpIfSmi(rdx, &miss);
18773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
18783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
18799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
18803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
18823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
18839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    GenerateLoadFunctionFromCell(cell, function, &miss);
18849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
18859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Load the (only) argument into rax.
18869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rax, Operand(rsp, 1 * kPointerSize));
1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check if the argument is a smi.
18899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label not_smi;
18909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  STATIC_ASSERT(kSmiTag == 0);
18919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfNotSmi(rax, &not_smi);
18929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ SmiToInteger32(rax, rax);
1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
18959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // otherwise.
18969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movl(rbx, rax);
18979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ sarl(rbx, Immediate(kBitsPerInt - 1));
1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Do bitwise not or do nothing depending on ebx.
19009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ xorl(rax, rbx);
1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Add 1 or do nothing depending on ebx.
19039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ subl(rax, rbx);
19049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
19059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If the result is still negative, go to the slow case.
19069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // This only happens for the most negative smi.
19079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label slow;
19089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(negative, &slow);
19099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
19109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Smi case done.
19119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ Integer32ToSmi(rax, rax);
19129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(2 * kPointerSize);
19139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
19149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check if the argument is a heap number and load its value.
19159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&not_smi);
1916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
19179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
1918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check the sign of the argument. If the argument is positive,
19209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // just return it.
19219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label negative_sign;
19229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int sign_mask_shift =
19239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      (HeapNumber::kExponentOffset - HeapNumber::kValueOffset) * kBitsPerByte;
19249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdi, static_cast<int64_t>(HeapNumber::kSignMask) << sign_mask_shift,
19259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block          RelocInfo::NONE);
19269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ testq(rbx, rdi);
19279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_zero, &negative_sign);
19289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(2 * kPointerSize);
1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If the argument is negative, clear the sign, and return a new
19319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // number. We still have the sign mask in rdi.
19329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&negative_sign);
19339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ xor_(rbx, rdi);
19349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ AllocateHeapNumber(rax, rdx, &slow);
19359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx);
19369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(2 * kPointerSize);
1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Tail call the full function. We do not have to patch the receiver
19399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // because the function makes no use of it.
19409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&slow);
19413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
1943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
1944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
1945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
19489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rcx: function name.
19493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
19523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
1953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19563ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall(
195744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    const CallOptimization& optimization,
19583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
19593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
19603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
19613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
19623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
196344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(optimization.is_simple_api_call());
196444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Bail out if object is a global object as we don't want to
196544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // repatch it to global receiver.
19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (object->IsGlobalObject()) return Handle<Code>::null();
19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!cell.is_null()) return Handle<Code>::null();
19683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject()) return Handle<Code>::null();
196944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int depth = optimization.GetPrototypeDepthOfExpectedType(
19703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<JSObject>::cast(object), holder);
19713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (depth == kInvalidProtoDepth) return Handle<Code>::null();
197244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
197344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss, miss_before_stack_reserved;
197444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss_before_stack_reserved);
197544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
197644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the receiver from the stack.
197744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int argc = arguments().immediate();
197844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
197944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
198044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the receiver isn't a smi.
198144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ JumpIfSmi(rdx, &miss_before_stack_reserved);
198244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
198344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
198444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const(), 1);
198544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const_fast_api(), 1);
198644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
198744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate space for v8::Arguments implicit values. Must be initialized
198844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // before calling any runtime function.
198944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
199044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
199144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the maps haven't changed and find a Holder as a side effect.
19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, depth, &miss);
199444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
199544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Move the return address on top of the stack.
199644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(rax, Operand(rsp, 3 * kPointerSize));
199744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(Operand(rsp, 0 * kPointerSize), rax);
199844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateFastApiCall(masm(), optimization, argc);
200044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
200144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss);
200244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
200344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
200444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss_before_stack_reserved);
20053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
200644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
200744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Return the generated code.
200844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return GetCode(function);
200944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
201044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
201144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
20123ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
20133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> function,
20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
20169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                   CheckType check) {
2017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
20189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rcx                 : function name
20199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[0]              : return address
20209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[8]              : argument argc
20219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[16]             : argument argc - 1
20229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ...
20239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[argc * 8]       : argument 1
20249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[(argc + 1) * 8] : argument 0 = receiver
2025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
202744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
20283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder,
20293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Handle<JSGlobalPropertyCell>::null(),
20303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          function, name);
20313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
20330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
2034e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
203544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss;
203644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss);
2037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the receiver from the stack.
20399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
20409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
2041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the receiver isn't a smi.
20439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (check != NUMBER_CHECK) {
204444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ JumpIfSmi(rdx, &miss);
20459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
2046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Make sure that it's okay not to patch the on stack receiver
20489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // unless we're doing a receiver map check.
20499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
205144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
20529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  switch (check) {
20539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    case RECEIVER_MAP_CHECK:
205444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ IncrementCounter(counters->call_const(), 1);
2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Check that the maps haven't changed.
20573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax,
20583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      rdi, name, &miss);
2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // Patch the receiver on the stack with the global proxy if
20619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      // necessary.
20629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      if (object->IsGlobalObject()) {
20639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
20649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
20659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      }
20669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      break;
2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    case STRING_CHECK:
20693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
20709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        // Check that the object is a two-byte string or a symbol.
20719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax);
20729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ j(above_equal, &miss);
20739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        // Check that the maps starting from the prototype haven't changed.
20749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        GenerateDirectLoadGlobalFunctionPrototype(
20759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block            masm(), Context::STRING_FUNCTION_INDEX, rax, &miss);
20763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
20773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
20783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            rax, holder, rbx, rdx, rdi, name, &miss);
20793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
208085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
208185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // requires boxing.
208285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        __ jmp(&miss);
20833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
20843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
20853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case NUMBER_CHECK:
20873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
20889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        Label fast;
20899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        // Check that the object is a smi or a heap number.
20909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ JumpIfSmi(rdx, &fast);
20919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax);
20929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ j(not_equal, &miss);
20939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ bind(&fast);
20949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        // Check that the maps starting from the prototype haven't changed.
20959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        GenerateDirectLoadGlobalFunctionPrototype(
20969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block            masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss);
20973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
20983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
20993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            rax, holder, rbx, rdx, rdi, name, &miss);
21003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
210185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
210285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // requires boxing.
210385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        __ jmp(&miss);
21043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
21053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
21063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case BOOLEAN_CHECK:
21083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
21099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        Label fast;
21109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        // Check that the object is a boolean.
21119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ CompareRoot(rdx, Heap::kTrueValueRootIndex);
21129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ j(equal, &fast);
21139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ CompareRoot(rdx, Heap::kFalseValueRootIndex);
21149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ j(not_equal, &miss);
21159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        __ bind(&fast);
21169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        // Check that the maps starting from the prototype haven't changed.
21179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        GenerateDirectLoadGlobalFunctionPrototype(
21189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block            masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss);
21193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
21203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
21213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            rax, holder, rbx, rdx, rdi, name, &miss);
21223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
21233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
21243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // requires boxing.
21253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&miss);
21269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      }
21279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      break;
21289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
2129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
2133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
2135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Handle call cache miss.
2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
21383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
21419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(function);
2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
21463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
21473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
2148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
21499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rcx                 : function name
21509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[0]              : return address
21519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[8]              : argument argc
21529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[16]             : argument argc - 1
21539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ...
21549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[argc * 8]       : argument 1
21559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[(argc + 1) * 8] : argument 0 = receiver
2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
21589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateNameCheck(name, &miss);
2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the number of arguments.
21619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
21659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
21669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the receiver from the stack.
21679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
21689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
21693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_);
21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax,
21713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   &miss);
21729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
21739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Restore receiver.
21749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
21759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
21769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the function really is a function.
21779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(rax, &miss);
21789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
21799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
21809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
21819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Patch the receiver on the stack with the global proxy if
21829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // necessary.
21839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (object->IsGlobalObject()) {
21849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
21859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
21869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
21879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
21889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Invoke the function.
21899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdi, rax);
21903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
2193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
2194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
21959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
21969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Handle load cache miss.
2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
21983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22053ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal(
22063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
22073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
22083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
22093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
22103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
22129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rcx                 : function name
22139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[0]              : return address
22149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[8]              : argument argc
22159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[16]             : argument argc - 1
22169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ...
22179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[argc * 8]       : argument 1
22189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // rsp[(argc + 1) * 8] : argument 0 = receiver
2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
22209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
222144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
22223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
22233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
22243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
22259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
22269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
22289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateNameCheck(name, &miss);
2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the number of arguments.
22319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const int argc = arguments().immediate();
22329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateGlobalReceiverCheck(object, holder, name, &miss);
22339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadFunctionFromCell(cell, function, &miss);
22349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
22359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Patch the receiver on the stack with the global proxy.
22369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (object->IsGlobalObject()) {
22379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
22389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
22399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
22409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the context (function already in rdi).
22429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
22439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
22449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Jump to the cached code (tail call).
224544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
224644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline(), 1);
22479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ParameterCount expected(function->shared()->formal_parameter_count());
22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We call indirectly through the code field in the function to
22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // allow recompilation to take effect without changing any of the
22533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // call sites.
22543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION,
22563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                NullCallWrapper(), call_kind);
22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Handle call cache miss.
2259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
226044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline_miss(), 1);
22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
22649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(NORMAL, name);
2265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
22699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                  int index,
22703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<Map> transition,
22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<String> name) {
2272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
22739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : value
22749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
2275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rdx    : receiver
22769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
2277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
2278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label miss;
2279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Generate store field code.  Preserves receiver and name on jump to miss.
22813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss);
2282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Handle store cache miss.
2284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
228544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
22869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Return the generated code.
22893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
2291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22933ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback(
22943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
22953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback,
22963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax    : value
2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
23004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- rdx    : receiver
2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
23063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(rdx, Handle<Map>(object->map()), &miss,
23073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
23114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ CheckAccessGlobalProxy(rdx, rbx, &miss);
2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(rbx);  // remove the return address
23199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rdx);  // receiver
23203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Push(callback);  // callback info
23219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rcx);  // name
23229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rax);  // value
23239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rbx);  // restore return address
23249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
23259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Do tail-call to the runtime system.
23269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ExternalReference store_callback_property =
232744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
23289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ TailCallExternalReference(store_callback_property, 4, 1);
2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
233244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
23369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CALLBACKS, name);
2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23403ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor(
23413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
23423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax    : value
2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
23464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- rdx    : receiver
2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
23523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss,
23533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (receiver->IsJSGlobalProxy()) {
23574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ CheckAccessGlobalProxy(rdx, rbx, &miss);
2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(rbx);  // remove the return address
23654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(rdx);  // receiver
2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rcx);  // name
2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rax);  // value
2368e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ Push(Smi::FromInt(strict_mode_));
2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rbx);  // restore return address
2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_ic_property =
237344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
2374e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ TailCallExternalReference(store_ic_property, 4, 1);
2375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
237844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal(
23873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> object,
23883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
23893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax    : value
2392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
23934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- rdx    : receiver
2394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
23994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Handle<Map>(object->map()));
2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Compute the cell operand to use.
24043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rbx, cell);
24053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Operand cell_operand = FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset);
24063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the value in the cell is not the hole. If it is, this
24081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // cell could have been deleted and reintroducing the global needs
24091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // to update the property details in the property dictionary of the
24101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // global object. We bail out to the runtime system to do that.
24113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareRoot(cell_operand, Heap::kTheHoleValueRootIndex);
24121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ j(equal, &miss);
24131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Store the value in the cell.
24153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(cell_operand, rax);
24163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Cells are always rescanned, so no write barrier here.
2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the value (register rax).
241944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
242044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline(), 1);
2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
242544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
242644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
24355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                       int index,
24363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<Map> transition,
24373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<String> name) {
2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax     : value
2440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- rcx     : key
2441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- rdx     : receiver
2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0]  : return address
2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
244644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
244744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_store_field(), 1);
2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
24503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rcx, name);
2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Generate store field code.  Preserves receiver and name on jump to miss.
24543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss);
2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
245844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_store_field(), 1);
245944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
24633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement(
24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
2469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
2470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rax    : value
2471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rcx    : key
2472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rdx    : receiver
2473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rsp[0] : return address
2474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
24753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2476589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
2477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
24783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub =
24793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode();
24803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
2482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
2485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
24873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
2488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
24913ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
24923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
24933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_stubs,
24943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* transitioned_maps) {
2495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : value
2497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rcx    : key
2498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
2499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0] : return address
2500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
25023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(rdx, &miss, Label::kNear);
2503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
25043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
2505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int receiver_count = receiver_maps->length();
25063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < receiver_count; ++i) {
2507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check map and tail call if there's a match
25083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Cmp(rdi, receiver_maps->at(i));
25093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (transitioned_maps->at(i).is_null()) {
25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET);
25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
25123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label next_map;
25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &next_map, Label::kNear);
25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(rbx, transitioned_maps->at(i), RelocInfo::EMBEDDED_OBJECT);
25153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&next_map);
25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
252144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
2523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Return the generated code.
25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
2526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
25293ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
25303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> object,
25313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> last) {
25329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
25339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
25349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
25359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
25369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
25379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
25387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that receiver is not a smi.
25409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ JumpIfSmi(rax, &miss);
25417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check the maps of the full prototype chain. Also check that
25439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // global property cells up to (but not including) the last object
25449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // in the prototype chain are empty.
25459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss);
25469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // If the last object in the prototype chain is a global object,
25489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // check that the global property cell is empty.
25499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (last->IsGlobalObject()) {
25503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateCheckPropertyCell(
25513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm(), Handle<GlobalObject>::cast(last), name, rdx, &miss);
25527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
25537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
25549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return undefined if maps of the full prototype chain are still the
25559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // same and no global property with this name contains a value.
25569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
25579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(0);
25589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
25609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
25619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NONEXISTENT, factory()->empty_string());
25649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
25659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
25683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
25699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                int index,
25703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
25719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
25729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
25739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
25749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
25759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
25769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
25779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadField(object, holder, rax, rbx, rdx, rdi, index, name, &miss);
25799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
25809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
25819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
25839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(FIELD, name);
25849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
25859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback(
25883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
25893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
25913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
25929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
25939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
25949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
25959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
25969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
25979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(object, holder, rax, rcx, rdx, rbx, rdi, callback,
25993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       name, &miss);
26009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
26019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
26029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
26049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CALLBACKS, name);
26059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
26069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26083ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
26093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
26103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> value,
26113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name) {
26129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
26139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
26149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
26159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
26169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
26179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
26189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss);
26209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
26219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
26229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
26249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CONSTANT_FUNCTION, name);
26259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
26269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26283ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver,
26293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
26303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
26319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
26329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
26339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
26349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
26359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
26369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
26373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
26389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  LookupPostInterceptor(holder, name, &lookup);
26399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // TODO(368): Compile in the whole chain: all the interceptors in
26419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // prototypes and ultimate answer.
26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(receiver, holder, &lookup, rax, rcx, rdx, rbx, rdi,
26433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          name, &miss);
26449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
26459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
26469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
26489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(INTERCEPTOR, name);
26499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
26509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26523ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal(
26533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
26543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
26553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
26573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_dont_delete) {
26589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
26599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
26609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
26619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
26629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
26639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
26649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the maps haven't changed.
26663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(rax, &miss);
26679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  CheckPrototypes(object, rax, holder, rbx, rdx, rdi, name, &miss);
26689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the value from the cell.
26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(rbx, cell);
26719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
26729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check for deleted property if property can actually be deleted.
26749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (!is_dont_delete) {
26759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
26769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ j(equal, &miss);
26779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else if (FLAG_debug_code) {
26789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
26799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ Check(not_equal, "DontDelete cells can't contain the hole");
26809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
26819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
268244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
268344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub(), 1);
26849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rax, rbx);
26859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ ret(0);
26869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
26879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
268844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub_miss(), 1);
26899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
26907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
26919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
26929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(NORMAL, name);
26939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
26947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
26957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
26963ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
26973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> receiver,
26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> holder,
26999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                                     int index) {
27009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
27019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax     : key
27029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx     : receiver
27039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
27049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
27059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
27067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
270744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
270844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_field(), 1);
27097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
27113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
27129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
27137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadField(receiver, holder, rdx, rbx, rcx, rdi, index, name, &miss);
27157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
271744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_field(), 1);
27189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
27197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
27219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(FIELD, name);
27229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
27237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
27253ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback(
27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
27283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
27293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
27309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
27319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax     : key
27329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx     : receiver
27339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
27349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
27359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
273644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
273744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_callback(), 1);
2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
27419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx, rdi, callback,
27443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       name, &miss);
27459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
274644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_callback(), 1);
27479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2748bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
27499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
27509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CALLBACKS, name);
27519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
27528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2753bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
27543ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant(
27553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
27563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> value) {
27599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
27609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
27619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
27629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
27639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
27649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
2765bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
276644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
276744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_constant_function(), 1);
2768bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
27699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
27719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
27728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
27739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadConstant(receiver, holder, rdx, rbx, rcx, rdi,
27749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                       value, name, &miss);
27759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
277644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_constant_function(), 1);
27779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
27788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
27799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
27809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CONSTANT_FUNCTION, name);
27819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
27828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
27838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
27843ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
27873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
27889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
27899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
27909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
27919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
27929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
27939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
279444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
279544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_interceptor(), 1);
27968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
27979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
27983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
27999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
28009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
28013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
28029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  LookupPostInterceptor(holder, name, &lookup);
28033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(receiver, holder, &lookup, rdx, rax, rcx, rbx, rdi,
28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          name, &miss);
28059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
280644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_interceptor(), 1);
28079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
28089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
28099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
28109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(INTERCEPTOR, name);
2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28143ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
28153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
28169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
28179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
28189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
28199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
28209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
28219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
28223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
282344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
282444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_array_length(), 1);
28253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
28273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
28289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
28293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadArrayLength(masm(), rdx, rcx, &miss);
28319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
283244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_array_length(), 1);
28339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
28343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
28369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CALLBACKS, name);
28379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
28383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28403ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
28413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
28429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
28439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
28449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
28459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
28469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
28479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
28483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
284944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
285044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_string_length(), 1);
28513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
28533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
28549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
28553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss, true);
28579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
285844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_string_length(), 1);
28599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
28603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
28629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CALLBACKS, name);
28639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
28643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
28689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
28699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
28709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
28719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
28729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
28739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
28743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
287544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
287644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_function_prototype(), 1);
2877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check that the name has not changed.
28793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rax, name);
28809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ j(not_equal, &miss);
2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
28839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
288444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
28859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
28869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
28879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
28889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return GetCode(CALLBACKS, name);
2889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement(
28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
28949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
28959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
28969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
289744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //  -- rsp[0] : return address
28989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
2899589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
29003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode();
29013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
2903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
2905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
29083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
2909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29123ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic(
29133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
29143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_ics) {
2915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : key
2917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
2918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0] : return address
2919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(rdx, &miss);
2922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register map_reg = rbx;
2924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset));
2925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int receiver_count = receiver_maps->length();
2926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int current = 0; current < receiver_count; ++current) {
2927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check map and tail call if there's a match
29283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Cmp(map_reg, receiver_maps->at(current));
29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, handler_ics->at(current), RelocInfo::CODE_TARGET);
2930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
29319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
2932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __  bind(&miss);
29339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
29349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
29359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Return the generated code.
29363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Specialized stub for constructing objects from functions which only have only
2941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// simple assignments of the form this.x = ...; in their body.
29423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub(
29433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function) {
2944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax : argc
2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rdi : constructor
2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[4] : last argument
2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_stub_call;
2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use r8 for holding undefined which is used in several places below.
295344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(r8, factory()->undefined_value());
2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check to see whether there are any break points in the function code. If
2957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // there are jump to the generic constructor stub which calls the actual
2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code for the function thereby hitting the break points.
2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kDebugInfoOffset));
2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmpq(rbx, r8);
2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &generic_stub_call);
2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map and verify that it is in fact a map.
2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Will both indicate a NULL and a Smi.
296869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(rbx, &generic_stub_call);
2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(rbx, MAP_TYPE, rcx);
2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &generic_stub_call);
2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cannot construct functions this way.
2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdi: constructor
2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rbx: initial map
2977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpInstanceType(rbx, JS_FUNCTION_TYPE);
2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Assert(not_equal, "Function constructed by construct stub.");
2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Now allocate the JSObject in new space.
2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdi: constructor
2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rbx: initial map
2984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movzxbq(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset));
2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ shl(rcx, Immediate(kPointerSizeLog2));
29863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AllocateInNewSpace(rcx, rdx, rcx, no_reg,
29873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &generic_stub_call, NO_ALLOCATION_FLAGS);
2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSObject, now initialize the fields and add the heap tag.
2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rbx: initial map
2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdx: JSObject (untagged)
2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(Operand(rdx, JSObject::kMapOffset), rbx);
299344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(rbx, factory()->empty_fixed_array());
2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(Operand(rdx, JSObject::kPropertiesOffset), rbx);
2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(Operand(rdx, JSObject::kElementsOffset), rbx);
2996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: argc
2998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdx: JSObject (untagged)
2999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the address of the first in-object property into r9.
3000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(r9, Operand(rdx, JSObject::kHeaderSize));
3001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the first argument. The stack contains only the
3002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // return address on top of the argc arguments.
3003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(rcx, Operand(rsp, rax, times_pointer_size, 0));
3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: argc
3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rcx: first argument
3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdx: JSObject (untagged)
3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r8: undefined
3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r9: first in-object property of the JSObject
3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the initialized properties with a constant value or a passed argument
3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // depending on the this.x = ...; assignment in the function.
30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<SharedFunctionInfo> shared(function->shared());
3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (shared->IsThisPropertyAssignmentArgument(i)) {
3015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check if the argument assigned to the property is actually passed.
3016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // If argument is not passed the property is set to undefined,
3017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // otherwise find it on the stack.
3018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int arg_number = shared->GetThisPropertyAssignmentArgument(i);
3019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ movq(rbx, r8);
3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmpq(rax, Immediate(arg_number));
3021e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ cmovq(above, rbx, Operand(rcx, arg_number * -kPointerSize));
3022e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Store value in the property.
3023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ movq(Operand(r9, i * kPointerSize), rbx);
3024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
3025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to the constant value.
3026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
3027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ Move(Operand(r9, i * kPointerSize), constant);
3028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the unused in-object property fields with undefined.
30328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(function->has_initial_map());
3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = shared->this_property_assignments_count();
30348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang       i < function->initial_map()->inobject_properties();
3035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       i++) {
3036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(Operand(r9, i * kPointerSize), r8);
3037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: argc
3040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdx: JSObject (untagged)
3041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move argc to rbx and the JSObject to return to rax and tag it.
3042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rbx, rax);
3043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rax, rdx);
3044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ or_(rax, Immediate(kHeapObjectTag));
3045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: JSObject
3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rbx: argc
3048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack and return.
3049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(rcx);
3050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(rsp, Operand(rsp, rbx, times_pointer_size, 1 * kPointerSize));
3051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rcx);
305244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
305344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects(), 1);
305444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects_stub(), 1);
3055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
3056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic stub in case the specialized code cannot handle the
3058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // construction.
3059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_stub_call);
30603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code = isolate()->builtins()->JSConstructStubGeneric();
30613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(code, RelocInfo::CODE_TARGET);
3062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode();
3065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __
30693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm)
30703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
30713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
30723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
30733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
30741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
30751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rax    : key
30761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rdx    : receiver
30771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rsp[0] : return address
30781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
30793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, miss_force_generic;
3080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
30813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
30823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
30831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
30843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(rax, &miss_force_generic);
30853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger32(rbx, rax);
30863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
30871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
30883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check whether the elements is a number dictionary.
30893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rdx: receiver
30903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rax: key
30913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rbx: key as untagged int32
30923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rcx: elements
30933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax);
30943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
30953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
30963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
3097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
30983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rax    : key
3099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
31003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rsp[0]  : return address
3101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
31023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
31033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
31043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
3105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
31063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
31073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
31083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rax    : key
31093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rdx    : receiver
31103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rsp[0]  : return address
31113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
31123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_ic =
31133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
31143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray(
3118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3119589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
3120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : key
3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
3123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0] : return address
3124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label slow, miss_force_generic;
3126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
3129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
3131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(rax, &miss_force_generic);
31321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
31331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the index is in range.
3134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
31351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ SmiToInteger32(rcx, rax);
313669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmpq(rax, FieldOperand(rbx, ExternalArray::kLengthOffset));
31371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
3138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &miss_force_generic);
31391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
31401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rax: index (as a smi)
31411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rdx: receiver (JSObject)
31421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rcx: untagged index
31431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rbx: elements array
31441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
31451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rbx: base pointer of external storage
31463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3147589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
31481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
31491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3150589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
3151589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
31521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0));
31531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3154589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
31551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0));
31561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3157589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
31581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0));
31591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3160589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
31611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0));
31621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3163589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
31641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movl(rcx, Operand(rbx, rcx, times_4, 0));
31651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3166589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
31671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0));
31681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3169589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
3170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ movsd(xmm0, Operand(rbx, rcx, times_8, 0));
3171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
31721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    default:
31731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
31741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
31751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
31761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
31771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rax: index
31781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rdx: receiver
31791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For integer array types:
31801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rcx: value
31811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For floating-point array type:
31821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // xmm0: value as double.
31831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
31841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(kSmiValueSize == 32);
3185589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
31861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the UnsignedInt array type, we need to see whether
31871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // the value can be represented in a Smi. If not, we need to convert
31881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // it to a HeapNumber.
3189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label box_int;
31901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfUIntNotValidSmiValue(rcx, &box_int, Label::kNear);
31921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
31931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Integer32ToSmi(rax, rcx);
31941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
31951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
31961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&box_int);
31971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
31981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Allocate a HeapNumber for the int and perform int-to-double
31991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // conversion.
32001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // The value is zero-extended since we loaded the value from memory
32011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // with movl.
32021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cvtqsi2sd(xmm0, rcx);
32031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ AllocateHeapNumber(rcx, rbx, &slow);
32051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Set the value.
32061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
32071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ movq(rax, rcx);
32081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
3209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
3210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch             elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
32111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the floating-point array type, we need to always allocate a
32121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // HeapNumber.
32131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ AllocateHeapNumber(rcx, rbx, &slow);
32141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Set the value.
32151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
32161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ movq(rax, rcx);
32171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
32181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
32191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Integer32ToSmi(rax, rcx);
32201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
32211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
32221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Slow case: Jump to runtime.
32241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
3225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm->isolate()->counters();
322644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
32271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
32291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rax    : key
32301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rdx    : receiver
32311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rsp[0]  : return address
32321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
32331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
32361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Miss case: Jump to runtime.
3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
32391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : key
3242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
3243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0]  : return address
3244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
3246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
32481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
32491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray(
3252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3253589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
32541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
32551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rax     : value
32561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rcx     : key
32571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rdx     : receiver
32581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rsp[0]  : return address
32591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
3260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label slow, miss_force_generic;
32611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
326444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
326544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the key is a smi.
3266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(rcx, &miss_force_generic);
32671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the index is in range.
3269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
32701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ SmiToInteger32(rdi, rcx);  // Untag the index.
327169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmpq(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset));
32721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
3273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &miss_force_generic);
32741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Handle both smis and HeapNumbers in the fast path. Go to the
32761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // runtime for all other kinds of values.
32771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rax: value
32781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rcx: key (a smi)
32791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rdx: receiver (a JSObject)
32801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rbx: elements array
32811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rdi: untagged key
3282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label check_heap_number;
3283589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
328444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Float to pixel conversion is only implemented in the runtime for now.
328544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ JumpIfNotSmi(rax, &slow);
328644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
3287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfNotSmi(rax, &check_heap_number, Label::kNear);
328844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
32891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // No more branches to slow case on this path.  Key and receiver not needed.
32901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ SmiToInteger32(rdx, rax);
32911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
32921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // rbx: base pointer of external storage
32933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3294589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
329544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      {  // Clamp the value to [0..255].
3296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Label done;
329744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ testl(rdx, Immediate(0xFFFFFF00));
3298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(zero, &done, Label::kNear);
329944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ setcc(negative, rdx);  // 1 if negative, 0 if positive.
330044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ decb(rdx);  // 0 if negative, 255 if positive.
330144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ bind(&done);
330244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
330344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ movb(Operand(rbx, rdi, times_1, 0), rdx);
330444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
3305589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
3306589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
33071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movb(Operand(rbx, rdi, times_1, 0), rdx);
33081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3309589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
3310589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
33111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movw(Operand(rbx, rdi, times_2, 0), rdx);
33121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3313589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
3314589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
33151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movl(Operand(rbx, rdi, times_4, 0), rdx);
33161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3317589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
33181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Need to perform int-to-float conversion.
33191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ cvtlsi2ss(xmm0, rdx);
33201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
33211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3322589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
3323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Need to perform int-to-float conversion.
3324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ cvtlsi2sd(xmm0, rdx);
3325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ movsd(Operand(rbx, rdi, times_8, 0), xmm0);
3326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3327589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_ELEMENTS:
33283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case FAST_SMI_ONLY_ELEMENTS:
3329589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_DOUBLE_ELEMENTS:
3330589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case DICTIONARY_ELEMENTS:
3331589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case NON_STRICT_ARGUMENTS_ELEMENTS:
33321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
33331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
33341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
33351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ret(0);
33361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
333744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // TODO(danno): handle heap number -> pixel array conversion
3338589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
333944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ bind(&check_heap_number);
334044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // rax: value
334144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // rcx: key (a smi)
334244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // rdx: receiver (a JSObject)
334344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // rbx: elements array
334444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // rdi: untagged key
334544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister);
334644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ j(not_equal, &slow);
334744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // No more branches to slow case on this path.
334844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
334944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The WebGL specification leaves the behavior of storing NaN and
335044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // +/-Infinity into integer arrays basically undefined. For more
335144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // reproducible behavior, convert these to zero.
335244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
335344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
33541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // rdi: untagged index
33551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // rbx: base pointer of external storage
335644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // top of FPU stack: value
3357589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
335844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ cvtsd2ss(xmm0, xmm0);
335944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
336044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ ret(0);
3361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ movsd(Operand(rbx, rdi, times_8, 0), xmm0);
3363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ ret(0);
336444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
336544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Perform float-to-int conversion with truncation (round-to-zero)
336644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // behavior.
336744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
336844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Convert to int32 and store the low byte/word.
336944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // If the value is NaN or +/-infinity, the result is 0x80000000,
337044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // which is automatically zero when taken mod 2^n, n < 32.
337144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // rdx: value (converted to an untagged integer)
337244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // rdi: untagged index
337344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // rbx: base pointer of external storage
33743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      switch (elements_kind) {
3375589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_BYTE_ELEMENTS:
3376589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
337744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          __ cvttsd2si(rdx, xmm0);
337844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          __ movb(Operand(rbx, rdi, times_1, 0), rdx);
337944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
3380589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_SHORT_ELEMENTS:
3381589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
338244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          __ cvttsd2si(rdx, xmm0);
338344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          __ movw(Operand(rbx, rdi, times_2, 0), rdx);
338444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
3385589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_INT_ELEMENTS:
3386589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_UNSIGNED_INT_ELEMENTS:
338744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          // Convert to int64, so that NaN and infinities become
338844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          // 0x8000000000000000, which is zero mod 2^32.
338944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          __ cvttsd2siq(rdx, xmm0);
339044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          __ movl(Operand(rbx, rdi, times_4, 0), rdx);
339144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
3392589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_PIXEL_ELEMENTS:
3393589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_FLOAT_ELEMENTS:
3394589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case EXTERNAL_DOUBLE_ELEMENTS:
3395589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case FAST_ELEMENTS:
33963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        case FAST_SMI_ONLY_ELEMENTS:
3397589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case FAST_DOUBLE_ELEMENTS:
3398589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case DICTIONARY_ELEMENTS:
3399589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        case NON_STRICT_ARGUMENTS_ELEMENTS:
340044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          UNREACHABLE();
340144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
34021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
340344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ ret(0);
34041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
34051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
34061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Slow case: call runtime.
34081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
34111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rax     : value
34121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rcx     : key
34131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rdx     : receiver
34141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- rsp[0]  : return address
34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
34161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
3419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Miss case: call runtime.
3421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : value
3425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rcx    : key
3426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
3427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0] : return address
3428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
3431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : key
3439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0] : return address
3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic;
34431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
34461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(rax, &miss_force_generic);
3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array.
3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
3452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AssertFastElements(rcx);
3453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is within bounds.
3455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
3456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &miss_force_generic);
3457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the result and make sure it's not the hole.
3459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2);
3460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(rbx, FieldOperand(rcx,
3461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            index.reg,
3462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            index.scale,
3463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            FixedArray::kHeaderSize));
3464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
3465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &miss_force_generic);
3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(rax, rbx);
3467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
3468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Code* code = masm->isolate()->builtins()->builtin(
3471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Builtins::kKeyedLoadIC_MissForceGeneric);
3472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic(code);
3473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
3474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
34773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
34783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
34793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
34803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rax    : key
34813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rdx    : receiver
34823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rsp[0] : return address
34833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
34843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label miss_force_generic, slow_allocate_heapnumber;
34853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
34863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
34873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
34883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
34893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a smi.
34903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(rax, &miss_force_generic);
34913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
34923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the elements array.
34933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
34943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AssertFastElements(rcx);
34953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
34963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is within bounds.
34973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
34983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(above_equal, &miss_force_generic);
34993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check for the hole
35013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger32(kScratchRegister, rax);
35023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
35033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmpl(FieldOperand(rcx, kScratchRegister, times_8, offset),
35043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          Immediate(kHoleNanUpper32));
35053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(equal, &miss_force_generic);
35063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Always allocate a heap number for the result.
35083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movsd(xmm0, FieldOperand(rcx, kScratchRegister, times_8,
35093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              FixedDoubleArray::kHeaderSize));
35103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber);
35113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Set the value.
35123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(rax, rcx);
35133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
35143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
35153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow_allocate_heapnumber);
35173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
35183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
35193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
35203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
35223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_ic =
35233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
35243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
35253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
35263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
35283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement(
35293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
35303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
35313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind elements_kind,
35323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
3533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax    : value
3535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rcx    : key
3536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx    : receiver
3537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0] : return address
3538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
35393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, transition_elements_kind, finish_store, grow;
35403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label check_capacity, slow;
3541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
3544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
3546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(rcx, &miss_force_generic);
3547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
35483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
35493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotSmi(rax, &transition_elements_kind);
35503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
35513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array and make sure it is a fast element array, not 'cow'.
3553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
3554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is within bounds.
3555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (is_js_array) {
3556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
35573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (grow_mode == ALLOW_JSARRAY_GROWTH) {
35583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(above_equal, &grow);
35593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
35603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(above_equal, &miss_force_generic);
35613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
3564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(above_equal, &miss_force_generic);
3565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
35673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset),
35683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 Heap::kFixedArrayMapRootIndex);
35693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &miss_force_generic);
35703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
35723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
35733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiToInteger32(rcx, rcx);
35743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
35753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            rax);
35763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
35773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Do the store and update the write barrier.
35783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(elements_kind == FAST_ELEMENTS);
35793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiToInteger32(rcx, rcx);
35803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lea(rcx,
35813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize));
35823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(Operand(rcx, 0), rax);
35833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure to preserve the value in register rax.
35843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(rbx, rax);
35853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWrite(rdi, rcx, rbx, kDontSaveFPRegs);
35863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Done.
3589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
3590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle store cache miss.
3592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic_force_generic =
3594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
35963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
35983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
35993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(ic_miss, RelocInfo::CODE_TARGET);
36003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
36023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array by a single element if possible.
36033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
36043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
36063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime. Flags are already set by previous
36073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // compare.
36083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &miss_force_generic);
36093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
36113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
36123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
36133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(rdi, Heap::kEmptyFixedArrayRootIndex);
36143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &check_capacity);
36153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
36173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, rdi, rbx, r8, &slow, TAG_OBJECT);
36183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rax: value
36203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rcx: key
36213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdx: receiver
36223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdi: elements
36233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
36243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(FieldOperand(rdi, JSObject::kMapOffset),
36253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            masm->isolate()->factory()->fixed_array_map());
36263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(FieldOperand(rdi, FixedArray::kLengthOffset),
36273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Smi::FromInt(JSArray::kPreallocatedArrayElements));
36283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(rbx, Heap::kTheHoleValueRootIndex);
36293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
36303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(FieldOperand(rdi, FixedArray::SizeFor(i)), rbx);
36313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
36323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Store the element at index zero.
36343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(FieldOperand(rdi, FixedArray::SizeFor(0)), rax);
36353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
36373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rdi);
36383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(rdx, JSObject::kElementsOffset, rdi, rbx,
36393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
36403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
36423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(FieldOperand(rdx, JSArray::kLengthOffset), Smi::FromInt(1));
36433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ret(0);
36443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
36463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for cow elements, in general they are not handled by this stub.
36473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset),
36483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Heap::kFixedCOWArrayMapRootIndex);
36493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, &miss_force_generic);
36503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rax: value
36523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rcx: key
36533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdx: receiver
36543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdi: elements
36553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
36563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmpq(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
36573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &slow);
36583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
36603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset),
36613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Smi::FromInt(1));
36623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
36633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
36653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
36663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(ic_slow, RelocInfo::CODE_TARGET);
36673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
36681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
36691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
36713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
36723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm,
36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
36743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
36753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
36763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rax    : value
36773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rcx    : key
36783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rdx    : receiver
36793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rsp[0] : return address
36803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
36813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, transition_elements_kind, finish_store;
36823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label grow, slow, check_capacity;
36833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
36853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
36863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a smi.
36883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(rcx, &miss_force_generic);
36893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the elements array.
36913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
36923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AssertFastElements(rdi);
36933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is within bounds.
36953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (is_js_array) {
36963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
36973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (grow_mode == ALLOW_JSARRAY_GROWTH) {
36983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ j(above_equal, &grow);
36993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
37003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ j(above_equal, &miss_force_generic);
37013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
37023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
37033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ SmiCompare(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset));
37043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &miss_force_generic);
37053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
37063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Handle smi values specially
37083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
37093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger32(rcx, rcx);
37103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0,
37113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 &transition_elements_kind);
37123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
37133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Handle store cache miss, replacing the ic with the generic stub.
37153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
37163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> ic_force_generic =
37173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
37183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
37193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
37213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Restore smi-tagging of rcx.
37223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Integer32ToSmi(rcx, rcx);
37233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
37243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(ic_miss, RelocInfo::CODE_TARGET);
37253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
37273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array by a single element if possible.
37283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
37293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
37313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime. Flags are already set by previous
37323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // compare.
37333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &miss_force_generic);
37343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Transition on values that can't be stored in a FixedDoubleArray.
37363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label value_is_smi;
37373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(rax, &value_is_smi);
37383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
37393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Heap::kHeapNumberMapRootIndex);
37403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &transition_elements_kind);
37413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&value_is_smi);
37423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
37443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
37453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
37463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(rdi, Heap::kEmptyFixedArrayRootIndex);
37473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &check_capacity);
37483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
37503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, rdi, rbx, r8, &slow, TAG_OBJECT);
37513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rax: value
37533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rcx: key
37543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdx: receiver
37553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdi: elements
37563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Initialize the new FixedDoubleArray. Leave elements unitialized for
37573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // efficiency, they are guaranteed to be initialized before use.
37583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(FieldOperand(rdi, JSObject::kMapOffset),
37593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            masm->isolate()->factory()->fixed_double_array_map());
37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(FieldOperand(rdi, FixedDoubleArray::kLengthOffset),
37613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Smi::FromInt(JSArray::kPreallocatedArrayElements));
37623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
37643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rdi);
37653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(rdx, JSObject::kElementsOffset, rdi, rbx,
37663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
37673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
37693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(FieldOperand(rdx, JSArray::kLengthOffset), Smi::FromInt(1));
37709413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch    __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
37713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
37723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
37743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rax: value
37753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rcx: key
37763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdx: receiver
37773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdi: elements
37783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
37793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmpq(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset));
37803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &slow);
37813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
37833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset),
37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Smi::FromInt(1));
37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
37863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
37883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
37893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(ic_slow, RelocInfo::CODE_TARGET);
37903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
37913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
37923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
3795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
3797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
3799