stub-cache-x64.cc revision 0d5e116f6aee03185f237311a943491bb079a768
14515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke// Copyright 2010 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
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_X64)
32f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h"
3480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "code-stubs.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h"
3780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "macro-assembler.h"
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//-----------------------------------------------------------------------------
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// StubCompiler static helper functions
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm)
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ProbeTable(MacroAssembler* masm,
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Code::Flags flags,
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       StubCache::Table table,
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Register name,
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Register offset) {
533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT_EQ(8, kPointerSize);
543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ASSERT_EQ(16, sizeof(StubCache::Entry));
553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // The offset register holds the entry offset times four (due to masking
563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // and shifting optimizations).
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference key_offset(SCTableReference::keyReference(table));
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(kScratchRegister, key_offset);
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the key in the entry matches the name.
623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Multiply entry offset by 16 to get the entry address. Since the
633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // offset register already holds the entry offset times four, multiply
643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // by a further four.
653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ cmpl(name, Operand(kScratchRegister, offset, times_4, 0));
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the code entry from the cache.
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use key_offset + kPointerSize, rather than loading value_offset.
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(kScratchRegister,
703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          Operand(kScratchRegister, offset, times_4, kPointerSize));
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the flags match what we're looking for.
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movl(offset, FieldOperand(kScratchRegister, Code::kFlagsOffset));
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(offset, Immediate(~Code::kFlagsNotUsedInLookup));
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmpl(offset, Immediate(flags));
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the first instruction in the code stub.
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ addq(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag));
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(kScratchRegister);
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Helper function used to check that the dictionary doesn't contain
863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// the property. This function may return false negatives, so miss_label
873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// must always call a backup property check that is complete.
883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// This function is safe to call if the receiver has fast properties.
893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Name must be a symbol and receiver must be a heap object.
903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                             Label* miss_label,
923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                             Register receiver,
933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                             String* name,
943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                             Register r0,
953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                             Register r1) {
963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(name->IsSymbol());
973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ IncrementCounter(&Counters::negative_lookups, 1);
983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ IncrementCounter(&Counters::negative_lookups_miss, 1);
993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1003bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label done;
1013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ movq(r0, FieldOperand(receiver, HeapObject::kMapOffset));
1023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const int kInterceptorOrAccessCheckNeededMask =
1043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
1053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Bail out if the receiver has a named interceptor or requires access checks.
1073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ testb(FieldOperand(r0, Map::kBitFieldOffset),
1083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch           Immediate(kInterceptorOrAccessCheckNeededMask));
1093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ j(not_zero, miss_label);
1103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check that receiver is a JSObject.
1123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE);
1133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ j(below, miss_label);
1143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Load properties array.
1163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register properties = r0;
1173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
1183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check that the properties array is a dictionary.
1203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset),
1213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                 Heap::kHashTableMapRootIndex);
1223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ j(not_equal, miss_label);
1233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Compute the capacity mask.
1253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const int kCapacityOffset =
1263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      StringDictionary::kHeaderSize +
1273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      StringDictionary::kCapacityIndex * kPointerSize;
1283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Generate an unrolled loop that performs a few probes before
1303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // giving up.
1313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  static const int kProbes = 4;
1323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const int kElementsStartOffset =
1333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      StringDictionary::kHeaderSize +
1343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      StringDictionary::kElementsStartIndex * kPointerSize;
1353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // If names of slots in range from 1 to kProbes - 1 for the hash value are
1373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // not equal to the name and kProbes-th slot is not used (its name is the
1383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // undefined value), it guarantees the hash table doesn't contain the
1393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // property. It's true even if some slots represent deleted properties
1403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // (their names are the null value).
1413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  for (int i = 0; i < kProbes; i++) {
1423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // r0 points to properties hash.
1433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Compute the masked index: (hash + i + i * i) & mask.
1443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    Register index = r1;
1453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Capacity is smi 2^n.
1463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset));
1473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ decl(index);
1483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ and_(index,
1493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch            Immediate(name->Hash() + StringDictionary::GetProbeOffset(i)));
1503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Scale the index by multiplying by the entry size.
1523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    ASSERT(StringDictionary::kEntrySize == 3);
1533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ lea(index, Operand(index, index, times_2, 0));  // index *= 3.
1543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    Register entity_name = r1;
1563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Having undefined at this place means the name is not contained.
1573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    ASSERT_EQ(kSmiTagSize, 1);
1583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ movq(entity_name, Operand(properties, index, times_pointer_size,
1593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                 kElementsStartOffset - kHeapObjectTag));
1603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ Cmp(entity_name, Factory::undefined_value());
1613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // __ jmp(miss_label);
1623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    if (i != kProbes - 1) {
1633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ j(equal, &done);
1643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Stop if found the property.
1663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ Cmp(entity_name, Handle<String>(name));
1673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ j(equal, miss_label);
1683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Check if the entry name is not a symbol.
1703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
1713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
1723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch               Immediate(kIsSymbolMask));
1733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ j(zero, miss_label);
1743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    } else {
1753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Give up probing if still not found the undefined value.
1763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ j(not_equal, miss_label);
1773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    }
1783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
1793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ bind(&done);
1813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ DecrementCounter(&Counters::negative_lookups_miss, 1);
1823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
1833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* code = NULL;
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kind == Code::LOAD_IC) {
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    code = Builtins::builtin(Builtins::LoadIC_Miss);
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(code);
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       int index,
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       Register prototype) {
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global or builtins object from the current context.
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(prototype,
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context from the global or builtins object.
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(prototype,
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the function from the global context.
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(prototype, Operand(prototype, Context::SlotOffset(index)));
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map.  The global functions all have initial maps.
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(prototype,
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the prototype from the initial map.
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
2190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    MacroAssembler* masm, int index, Register prototype, Label* miss) {
2200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check we're still in the same context.
2210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(prototype, Top::global());
2220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ cmpq(Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)),
2230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          prototype);
2240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ j(not_equal, miss);
2257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get the global function with the given index.
2267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  JSFunction* function = JSFunction::cast(Top::global_context()->get(index));
2277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load its initial map. The global functions all have initial maps.
2287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Move(prototype, Handle<Map>(function->initial_map()));
2297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load the prototype from the initial map.
2307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
2317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load a fast property out of a holder object (src). In-object properties
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are loaded directly otherwise the property is loaded from the properties
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// fixed array.
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register dst, Register src,
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            JSObject* holder, int index) {
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust for the number of properties stored in the holder.
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index -= holder->map()->inobject_properties();
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the property straight out of the holder.
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = holder->map()->instance_size() + (index * kPointerSize);
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(dst, FieldOperand(src, offset));
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate the offset into the properties array.
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset));
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(dst, FieldOperand(dst, offset));
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void PushInterceptorArguments(MacroAssembler* masm,
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register receiver,
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register holder,
258402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                     Register name,
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     JSObject* holder_obj) {
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(name);
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
2624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(!Heap::InNewSpace(interceptor));
2636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Move(kScratchRegister, Handle<Object>(interceptor));
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(kScratchRegister);
2656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(receiver);
2666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(holder);
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(FieldOperand(kScratchRegister, InterceptorInfo::kDataOffset));
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm,
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Code::Flags flags,
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register receiver,
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register name,
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register scratch,
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register extra) {
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  USE(extra);  // The register extra is not used on the X64 platform.
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that code is valid. The shifting code relies on the
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // entry size being 16.
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(sizeof(Entry) == 16);
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the flags do not name a specific type.
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that there are no register conflicts.
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(receiver));
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(name));
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(receiver, &miss);
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the map of the receiver and compute the hash.
294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movl(scratch, FieldOperand(name, String::kHashFieldOffset));
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use only the low 32 bits of the map pointer.
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ xor_(scratch, Immediate(flags));
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the primary table.
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ProbeTable(masm, flags, kPrimary, name, scratch);
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Primary miss: Compute hash for secondary probe.
304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ movl(scratch, FieldOperand(name, String::kHashFieldOffset));
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ xor_(scratch, Immediate(flags));
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ subl(scratch, name);
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ addl(scratch, Immediate(flags));
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch, Immediate((kSecondaryTableSize - 1) << kHeapObjectTagSize));
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the secondary table.
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ProbeTable(masm, flags, kSecondary, name, scratch);
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache miss: Fall-through and let caller handle the miss by
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // entering the runtime system.
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
321402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Both name_reg and receiver_reg are preserved on jumps to miss_label,
322402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// but may be destroyed if store is successful.
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm,
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      JSObject* object,
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      int index,
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Map* transition,
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register receiver_reg,
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register name_reg,
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch,
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* miss_label) {
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(receiver_reg, miss_label);
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Handle<Map>(object->map()));
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, miss_label);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform map transition for the receiver if necessary.
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The properties must be extended before we can store the value.
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We jump to a runtime call that extends the properties array.
352402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop(scratch);  // Return address.
353402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(receiver_reg);
354402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ Push(Handle<Map>(transition));
355402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(rax);
356402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(scratch);
3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ TailCallExternalReference(
358402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)), 3, 1);
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (transition != NULL) {
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the map of the object; no write barrier updating is
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // needed because the map is never in new space.
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset),
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Handle<Map>(transition));
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust for the number of properties stored in the object. Even in the
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // face of a transition we can use the old map here because the size of the
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object and the number of in-object properties is not going to change.
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index -= object->map()->inobject_properties();
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set the property straight into the object.
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = object->map()->instance_size() + (index * kPointerSize);
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(FieldOperand(receiver_reg, offset), rax);
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Pass the value being stored in the now unused name_reg.
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(name_reg, rax);
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ RecordWrite(receiver_reg, offset, name_reg, scratch);
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Write to the properties array.
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the properties array (optimistically).
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(FieldOperand(scratch, offset), rax);
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Pass the value being stored in the now unused name_reg.
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(name_reg, rax);
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ RecordWrite(scratch, offset, name_reg, receiver_reg);
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the value (register rax).
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch,
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss_label) {
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(receiver, miss_label);
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a JS array.
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, miss_label);
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load length directly from the JS array.
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rax, FieldOperand(receiver, JSArray::kLengthOffset));
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to check if an object is a string.  If the object is
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a string, the map's instance type is left in the scratch register.
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm,
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register receiver,
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register scratch,
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* smi,
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* non_string_object) {
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(receiver, smi);
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a string.
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movzxbq(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kNotStringTag != 0);
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ testl(scratch, Immediate(kNotStringTag));
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_zero, non_string_object);
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register receiver,
439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register scratch1,
440402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register scratch2,
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Label* miss) {
442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label check_wrapper;
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the object is a string leaving the instance type in the
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch register.
446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper);
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load length directly from the string.
4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(rax, FieldOperand(receiver, String::kLengthOffset));
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the object is a JSValue wrapper.
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&check_wrapper);
454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ cmpl(scratch1, Immediate(JS_VALUE_TYPE));
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, miss);
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the wrapped value is a string and load the length
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // directly if it is.
459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
4616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(rax, FieldOperand(scratch2, String::kLengthOffset));
462402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ret(0);
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   Register receiver,
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   Register holder,
469402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                                   Register name,
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   JSObject* holder_obj) {
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference ref =
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly));
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rax, Immediate(5));
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rbx, ref);
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CEntryStub stub(1);
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CallStub(&stub);
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register receiver,
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register result,
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register scratch,
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Label* miss_label) {
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ TryGetFunctionPrototype(receiver, result, miss_label);
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!result.is(rax)) __ movq(rax, result);
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Reserves space for the extra arguments to FastHandleApiCall in the
4966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// caller's frame.
4976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block//
4986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// These arguments are set by CheckPrototypes and GenerateFastApiCall.
4996ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
5006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
5016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[0] : return address
5026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[8] : last argument in the internal frame of the caller
5036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
5046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(scratch, Operand(rsp, 0));
5056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ subq(rsp, Immediate(4 * kPointerSize));
5066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(Operand(rsp, 0), scratch);
5076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Move(scratch, Smi::FromInt(0));
5086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(Operand(rsp, 1 * kPointerSize), scratch);
5096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(Operand(rsp, 2 * kPointerSize), scratch);
5106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(Operand(rsp, 3 * kPointerSize), scratch);
5116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(Operand(rsp, 4 * kPointerSize), scratch);
5126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Undoes the effects of ReserveSpaceForFastApiCall.
5166ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
5176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
5186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[0]  : return address
5196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[8]  : last fast api call extra argument
5206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ...
5216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[32] : first fast api call extra argument
5226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[40] : last argument in the internal frame
5236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
5246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(scratch, Operand(rsp, 0));
5256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(Operand(rsp, 4 * kPointerSize), scratch);
5266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ addq(rsp, Immediate(kPointerSize * 4));
5276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generates call to FastHandleApiCall builtin.
5316ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void GenerateFastApiCall(MacroAssembler* masm,
5326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                const CallOptimization& optimization,
5336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                int argc) {
5346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
5356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[0]              : return address
5366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[8]              : object passing the type check
5376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //                           (last fast api call extra argument,
5386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //                            set by CheckPrototypes)
5396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[16]             : api call data
5406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[24]             : api callback
5416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[32]             : api function
5426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //                           (first fast api call extra argument)
5436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[40]             : last argument
5446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ...
5456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[(argc + 5) * 8] : first argument
5466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[(argc + 6) * 8] : receiver
5476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
5486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the function and setup the context.
5506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  JSFunction* function = optimization.constant_function();
5516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Move(rdi, Handle<JSFunction>(function));
5526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
5536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Pass the additional arguments FastHandleApiCall expects.
5556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(Operand(rsp, 4 * kPointerSize), rdi);
5566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool info_loaded = false;
5576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* callback = optimization.api_call_info()->callback();
5586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (Heap::InNewSpace(callback)) {
5596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info_loaded = true;
5606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ Move(rcx, Handle<CallHandlerInfo>(optimization.api_call_info()));
5616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kCallbackOffset));
5626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ movq(Operand(rsp, 3 * kPointerSize), rbx);
5636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
5646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ Move(Operand(rsp, 3 * kPointerSize), Handle<Object>(callback));
5656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* call_data = optimization.api_call_info()->data();
5676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (Heap::InNewSpace(call_data)) {
5686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!info_loaded) {
5696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ Move(rcx, Handle<CallHandlerInfo>(optimization.api_call_info()));
5706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
5716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
5726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ movq(Operand(rsp, 2 * kPointerSize), rbx);
5736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
5746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ Move(Operand(rsp, 2 * kPointerSize), Handle<Object>(call_data));
5756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set the number of arguments.
5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(rax, Immediate(argc + 4));
5796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Jump to the fast api call builtin (tail call).
5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Code> code = Handle<Code>(
5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Builtins::builtin(Builtins::FastHandleApiCall));
5836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ParameterCount expected(0);
5846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ InvokeCode(code, expected, expected,
5856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                RelocInfo::CODE_TARGET, JUMP_FUNCTION);
5866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CallInterceptorCompiler BASE_EMBEDDED {
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
5916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallInterceptorCompiler(StubCompiler* stub_compiler,
5926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          const ParameterCount& arguments,
5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          Register name)
5946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : stub_compiler_(stub_compiler),
5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        arguments_(arguments),
5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        name_(name) {}
5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Compile(MacroAssembler* masm,
5996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               JSObject* object,
6006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               JSObject* holder,
6016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               String* name,
6026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               LookupResult* lookup,
6036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Register receiver,
6046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Register scratch1,
6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Register scratch2,
6063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch               Register scratch3,
6076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Label* miss) {
6086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(holder->HasNamedInterceptor());
6096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
6106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Check that the receiver isn't a smi.
6126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ JumpIfSmi(receiver, miss);
6136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CallOptimization optimization(lookup);
6156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (optimization.is_constant_call()) {
6176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      CompileCacheable(masm,
6186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       object,
6196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       receiver,
6206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       scratch1,
6216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       scratch2,
6223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                       scratch3,
6236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       holder,
6246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       lookup,
6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       name,
6266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       optimization,
6276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       miss);
6286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
6296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      CompileRegular(masm,
6306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     object,
6316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     receiver,
6326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     scratch1,
6336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     scratch2,
6343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                     scratch3,
6356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     name,
6366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     holder,
6376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     miss);
6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
6396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CompileCacheable(MacroAssembler* masm,
6436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        JSObject* object,
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Register receiver,
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Register scratch1,
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Register scratch2,
6473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                        Register scratch3,
648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                        JSObject* interceptor_holder,
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        LookupResult* lookup,
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        String* name,
6516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        const CallOptimization& optimization,
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Label* miss_label) {
6536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(optimization.is_constant_call());
6546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!lookup->holder()->IsGlobalObject());
6556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int depth1 = kInvalidProtoDepth;
6576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int depth2 = kInvalidProtoDepth;
6586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool can_do_fast_api_call = false;
6596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (optimization.is_simple_api_call() &&
6606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        !lookup->holder()->IsGlobalObject()) {
661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      depth1 =
662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          optimization.GetPrototypeDepthOfExpectedType(object,
663f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                                       interceptor_holder);
6646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (depth1 == kInvalidProtoDepth) {
665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        depth2 =
666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            optimization.GetPrototypeDepthOfExpectedType(interceptor_holder,
667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                                         lookup->holder());
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
6696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      can_do_fast_api_call = (depth1 != kInvalidProtoDepth) ||
6706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             (depth2 != kInvalidProtoDepth);
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ IncrementCounter(&Counters::call_const_interceptor, 1);
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
6766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1);
6776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ReserveSpaceForFastApiCall(masm, scratch1);
6786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
679402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Check that the maps from receiver to interceptor's holder
681f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // haven't changed and thus we can invoke interceptor.
6826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label miss_cleanup;
6836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
6846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register holder =
6857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        stub_compiler_->CheckPrototypes(object, receiver,
6867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                        interceptor_holder, scratch1,
6873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                        scratch2, scratch3, name, depth1, miss);
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke an interceptor and if it provides a value,
690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // branch to |regular_invoke|.
6916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label regular_invoke;
692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                        &regular_invoke);
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
695f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Interceptor returned nothing for this property.  Try to use cached
696f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // constant function.
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Check that the maps from interceptor's holder to constant function's
699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // holder haven't changed and thus we can use cached constant function.
7007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (interceptor_holder != lookup->holder()) {
7017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
7027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      lookup->holder(), scratch1,
7033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                      scratch2, scratch3, name, depth2, miss);
7047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
7057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // CheckPrototypes has a side effect of fetching a 'holder'
7067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // for API (object which is instanceof for the signature).  It's
7077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // safe to omit it here, as if present, it should be fetched
7087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // by the previous CheckPrototypes.
7097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(depth2 == kInvalidProtoDepth);
7107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke function.
7136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
7146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      GenerateFastApiCall(masm, optimization, arguments_.immediate());
7156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
7166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ InvokeFunction(optimization.constant_function(), arguments_,
7176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        JUMP_FUNCTION);
7186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Deferred code for fast API call case---clean preallocated space.
7216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
7226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ bind(&miss_cleanup);
7236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FreeSpaceForFastApiCall(masm, scratch1);
7246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ jmp(miss_label);
7256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
727f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke a regular function.
7286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ bind(&regular_invoke);
7296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
7306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FreeSpaceForFastApiCall(masm, scratch1);
7316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CompileRegular(MacroAssembler* masm,
7356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      JSObject* object,
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register receiver,
7376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Register scratch1,
7386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Register scratch2,
7393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                      Register scratch3,
7406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      String* name,
741f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                      JSObject* interceptor_holder,
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Label* miss_label) {
7436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register holder =
744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
7453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                        scratch1, scratch2, scratch3, name,
7466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                        miss_label);
7476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ EnterInternalFrame();
749402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Save the name_ register across the call.
750402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(name_);
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PushInterceptorArguments(masm,
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             receiver,
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             holder,
755402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                             name_,
756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                             interceptor_holder);
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
758402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ CallExternalReference(
759402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
760402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        5);
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Restore the name_ register.
763402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop(name_);
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LeaveInternalFrame();
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void LoadWithInterceptor(MacroAssembler* masm,
7686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register receiver,
7696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register holder,
7706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           JSObject* holder_obj,
7716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Label* interceptor_succeeded) {
7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ EnterInternalFrame();
7736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ push(holder);  // Save the holder.
7746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ push(name_);  // Save the name.
7756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CompileCallLoadPropertyWithInterceptor(masm,
7776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                           receiver,
7786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                           holder,
7796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                           name_,
7806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                           holder_obj);
7816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(name_);  // Restore the name.
7836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(receiver);  // Restore the holder.
7846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ LeaveInternalFrame();
7856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
7876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ j(not_equal, interceptor_succeeded);
7886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StubCompiler* stub_compiler_;
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const ParameterCount& arguments_;
792402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Register name_;
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generate code to check that a global property cell is empty. Create
7976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the property cell at compilation time if no cell exists for the
7986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property.
7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Object* GenerateCheckPropertyCell(MacroAssembler* masm,
8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                         GlobalObject* global,
8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                         String* name,
8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                         Register scratch,
8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                         Label* miss) {
8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* probe = global->EnsurePropertyCell(name);
8056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (probe->IsFailure()) return probe;
8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(cell->value()->IsTheHole());
8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Move(scratch, Handle<Object>(cell));
8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block         Factory::the_hole_value());
8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(not_equal, miss);
8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return cell;
8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM((masm()))
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
8219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid CallStubCompiler::GenerateNameCheck(String* name, Label* miss) {
8229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (kind_ == Code::KEYED_CALL_IC) {
8239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ Cmp(rcx, Handle<String>(name));
8249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ j(not_equal, miss);
8259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
8269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
8279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
8289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
82959151504615d929945dc59db37bf1166937748c6Steve Blockvoid CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object,
83059151504615d929945dc59db37bf1166937748c6Steve Block                                                   JSObject* holder,
83159151504615d929945dc59db37bf1166937748c6Steve Block                                                   String* name,
83259151504615d929945dc59db37bf1166937748c6Steve Block                                                   Label* miss) {
83359151504615d929945dc59db37bf1166937748c6Steve Block  ASSERT(holder->IsGlobalObject());
83459151504615d929945dc59db37bf1166937748c6Steve Block
83559151504615d929945dc59db37bf1166937748c6Steve Block  // Get the number of arguments.
83659151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
83759151504615d929945dc59db37bf1166937748c6Steve Block
83859151504615d929945dc59db37bf1166937748c6Steve Block  // Get the receiver from the stack.
83959151504615d929945dc59db37bf1166937748c6Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
84059151504615d929945dc59db37bf1166937748c6Steve Block
84159151504615d929945dc59db37bf1166937748c6Steve Block  // If the object is the holder then we know that it's a global
84259151504615d929945dc59db37bf1166937748c6Steve Block  // object which can only happen for contextual calls. In this case,
84359151504615d929945dc59db37bf1166937748c6Steve Block  // the receiver cannot be a smi.
84459151504615d929945dc59db37bf1166937748c6Steve Block  if (object != holder) {
84559151504615d929945dc59db37bf1166937748c6Steve Block    __ JumpIfSmi(rdx, miss);
84659151504615d929945dc59db37bf1166937748c6Steve Block  }
84759151504615d929945dc59db37bf1166937748c6Steve Block
84859151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the maps haven't changed.
84959151504615d929945dc59db37bf1166937748c6Steve Block  CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss);
85059151504615d929945dc59db37bf1166937748c6Steve Block}
85159151504615d929945dc59db37bf1166937748c6Steve Block
85259151504615d929945dc59db37bf1166937748c6Steve Block
85359151504615d929945dc59db37bf1166937748c6Steve Blockvoid CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
85459151504615d929945dc59db37bf1166937748c6Steve Block                                                    JSFunction* function,
85559151504615d929945dc59db37bf1166937748c6Steve Block                                                    Label* miss) {
85659151504615d929945dc59db37bf1166937748c6Steve Block  // Get the value from the cell.
85759151504615d929945dc59db37bf1166937748c6Steve Block  __ Move(rdi, Handle<JSGlobalPropertyCell>(cell));
85859151504615d929945dc59db37bf1166937748c6Steve Block  __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset));
85959151504615d929945dc59db37bf1166937748c6Steve Block
86059151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the cell contains the same function.
86159151504615d929945dc59db37bf1166937748c6Steve Block  if (Heap::InNewSpace(function)) {
86259151504615d929945dc59db37bf1166937748c6Steve Block    // We can't embed a pointer to a function in new space so we have
86359151504615d929945dc59db37bf1166937748c6Steve Block    // to verify that the shared function info is unchanged. This has
86459151504615d929945dc59db37bf1166937748c6Steve Block    // the nice side effect that multiple closures based on the same
86559151504615d929945dc59db37bf1166937748c6Steve Block    // function can all use this call IC. Before we load through the
86659151504615d929945dc59db37bf1166937748c6Steve Block    // function, we have to verify that it still is a function.
86759151504615d929945dc59db37bf1166937748c6Steve Block    __ JumpIfSmi(rdi, miss);
86859151504615d929945dc59db37bf1166937748c6Steve Block    __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax);
86959151504615d929945dc59db37bf1166937748c6Steve Block    __ j(not_equal, miss);
87059151504615d929945dc59db37bf1166937748c6Steve Block
87159151504615d929945dc59db37bf1166937748c6Steve Block    // Check the shared function info. Make sure it hasn't changed.
87259151504615d929945dc59db37bf1166937748c6Steve Block    __ Move(rax, Handle<SharedFunctionInfo>(function->shared()));
87359151504615d929945dc59db37bf1166937748c6Steve Block    __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax);
87459151504615d929945dc59db37bf1166937748c6Steve Block    __ j(not_equal, miss);
87559151504615d929945dc59db37bf1166937748c6Steve Block  } else {
87659151504615d929945dc59db37bf1166937748c6Steve Block    __ Cmp(rdi, Handle<JSFunction>(function));
87759151504615d929945dc59db37bf1166937748c6Steve Block    __ j(not_equal, miss);
87859151504615d929945dc59db37bf1166937748c6Steve Block  }
87959151504615d929945dc59db37bf1166937748c6Steve Block}
88059151504615d929945dc59db37bf1166937748c6Steve Block
88159151504615d929945dc59db37bf1166937748c6Steve Block
882bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* CallStubCompiler::GenerateMissBranch() {
883bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_);
884bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (obj->IsFailure()) return obj;
885bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
886bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return obj;
8877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
8887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallStubCompiler::CompileCallConstant(Object* object,
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              JSObject* holder,
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              JSFunction* function,
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              String* name,
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              StubCompiler::CheckType check) {
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
896402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rcx                 : function name
897402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[0]              : return address
898402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[8]              : argument argc
899402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[16]             : argument argc - 1
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ...
901402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[argc * 8]       : argument 1
902402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[(argc + 1) * 8] : argument 0 = receiver
903402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // -----------------------------------
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SharedFunctionInfo* function_info = function->shared();
9066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (function_info->HasCustomCallGenerator()) {
90725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    const int id = function_info->custom_call_generator_id();
90859151504615d929945dc59db37bf1166937748c6Steve Block    Object* result = CompileCustomCall(
90959151504615d929945dc59db37bf1166937748c6Steve Block        id, object, holder,  NULL, function, name);
9106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // undefined means bail out to regular compiler.
91159151504615d929945dc59db37bf1166937748c6Steve Block    if (!result->IsUndefined()) return result;
9126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss_in_smi_check;
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss_in_smi_check);
9179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check != NUMBER_CHECK) {
9246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ JumpIfSmi(rdx, &miss_in_smi_check);
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that it's okay not to patch the on stack receiver
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // unless we're doing a receiver map check.
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallOptimization optimization(function);
9326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int depth = kInvalidProtoDepth;
9336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
9346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (check) {
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RECEIVER_MAP_CHECK:
9376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ IncrementCounter(&Counters::call_const, 1);
9386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (optimization.is_simple_api_call() && !object->IsGlobalObject()) {
9406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        depth = optimization.GetPrototypeDepthOfExpectedType(
9416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            JSObject::cast(object), holder);
9426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
9436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (depth != kInvalidProtoDepth) {
9456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ IncrementCounter(&Counters::call_const_fast_api, 1);
9466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        ReserveSpaceForFastApiCall(masm(), rax);
9476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
9486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the maps haven't changed.
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckPrototypes(JSObject::cast(object), rdx, holder,
9513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                      rbx, rax, rdi, name, depth, &miss);
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Patch the receiver on the stack with the global proxy if
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // necessary.
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsGlobalObject()) {
9566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        ASSERT(depth == kInvalidProtoDepth);
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case STRING_CHECK:
963e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!function->IsBuiltin()) {
964e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Calling non-builtins with a value as receiver requires boxing.
965e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ jmp(&miss);
966e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
967e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a two-byte string or a symbol.
968402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax);
969e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ j(above_equal, &miss);
970e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
9717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
9720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::STRING_FUNCTION_INDEX, rax, &miss);
973402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
9743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                        rbx, rdx, rdi, name, &miss);
975e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case NUMBER_CHECK: {
979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!function->IsBuiltin()) {
980e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Calling non-builtins with a value as receiver requires boxing.
981e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ jmp(&miss);
982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a smi or a heap number.
985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ JumpIfSmi(rdx, &fast);
986402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax);
987e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ j(not_equal, &miss);
988e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
989e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
9907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
9910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss);
992402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
9933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                        rbx, rdx, rdi, name, &miss);
994e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case BOOLEAN_CHECK: {
999e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!function->IsBuiltin()) {
1000e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Calling non-builtins with a value as receiver requires boxing.
1001e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ jmp(&miss);
1002e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
1003e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
1004e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a boolean.
1005e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ CompareRoot(rdx, Heap::kTrueValueRootIndex);
1006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ j(equal, &fast);
1007e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ CompareRoot(rdx, Heap::kFalseValueRootIndex);
1008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ j(not_equal, &miss);
1009e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
1010e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
10117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
10120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss);
1013402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
10143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                        rbx, rdx, rdi, name, &miss);
1015e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (depth != kInvalidProtoDepth) {
10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    GenerateFastApiCall(masm(), optimization, argc);
10256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
10276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (depth != kInvalidProtoDepth) {
10326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    FreeSpaceForFastApiCall(masm(), rax);
10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Handle call cache miss.
10366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss_in_smi_check);
1037bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object* obj = GenerateMissBranch();
1038bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (obj->IsFailure()) return obj;
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
104125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1045402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuObject* CallStubCompiler::CompileCallField(JSObject* object,
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           JSObject* holder,
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           int index,
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           String* name) {
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1050402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rcx                 : function name
1051402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[0]              : return address
1052402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[8]              : argument argc
1053402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[16]             : argument argc - 1
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ...
1055402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[argc * 8]       : argument 1
1056402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[(argc + 1) * 8] : argument 0 = receiver
1057402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // -----------------------------------
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
10619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(rdx, &miss);
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do the right check and compute the holder register.
10703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi,
10713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                 name, &miss);
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), rdi, reg, holder, index);
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(rdi, &miss);
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx);
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy if
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary.
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION);
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1092bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object* obj = GenerateMissBranch();
1093bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (obj->IsFailure()) return obj;
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11006ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockObject* CallStubCompiler::CompileArrayPushCall(Object* object,
11016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               JSObject* holder,
110259151504615d929945dc59db37bf1166937748c6Steve Block                                               JSGlobalPropertyCell* cell,
11036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               JSFunction* function,
110459151504615d929945dc59db37bf1166937748c6Steve Block                                               String* name) {
11056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rcx                 : name
11076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[0]              : return address
11086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
11096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ...
11106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[(argc + 1) * 8] : receiver
11116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
11126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If object is not an array, bail out to regular call.
111459151504615d929945dc59db37bf1166937748c6Steve Block  if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value();
11156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
11176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
11199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack.
11216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
11226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
11236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
11256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ JumpIfSmi(rdx, &miss);
11266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CheckPrototypes(JSObject::cast(object),
11286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  rdx,
11296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  holder,
11306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  rbx,
11316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  rax,
11323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                  rdi,
11336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  name,
11346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  &miss);
11356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (argc == 0) {
11376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Noop, return the length.
11386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ ret((argc + 1) * kPointerSize);
11406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
1141756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Label call_builtin;
1142756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
11436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Get the elements array of the object.
11446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
11456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1146756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Check that the elements are in fast mode and writable.
11476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
11486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block           Factory::fixed_array_map());
1149756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ j(not_equal, &call_builtin);
11506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (argc == 1) {  // Otherwise fall through to call builtin.
1152756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      Label exit, with_write_barrier, attempt_to_grow_elements;
11536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Get the array's length into rax and calculate new length.
11559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
11566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
11579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      __ addl(rax, Immediate(argc));
11586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Get the element's length into rcx.
11609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      __ SmiToInteger32(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
11616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Check if we could survive without allocation.
11639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      __ cmpl(rax, rcx);
11646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(greater, &attempt_to_grow_elements);
11656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Save new length.
11679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
11686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Push the element.
11706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ movq(rcx, Operand(rsp, argc * kPointerSize));
11716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ lea(rdx, FieldOperand(rbx,
11729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                               rax, times_pointer_size,
11736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               FixedArray::kHeaderSize - argc * kPointerSize));
11746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ movq(Operand(rdx, 0), rcx);
11756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Check if value is a smi.
11779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      __ Integer32ToSmi(rax, rax);  // Return new length as smi.
11789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ JumpIfNotSmi(rcx, &with_write_barrier);
11806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ bind(&exit);
11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ ret((argc + 1) * kPointerSize);
11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ bind(&with_write_barrier);
11856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ InNewSpace(rbx, rcx, equal, &exit);
11876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      RecordWriteStub stub(rbx, rdx, rcx);
11896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ CallStub(&stub);
11909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ ret((argc + 1) * kPointerSize);
11926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ bind(&attempt_to_grow_elements);
11946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ExternalReference new_space_allocation_top =
11956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          ExternalReference::new_space_allocation_top_address();
11966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ExternalReference new_space_allocation_limit =
11976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          ExternalReference::new_space_allocation_limit_address();
11986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      const int kAllocationDelta = 4;
12006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Load top.
12016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ movq(rcx, new_space_allocation_top);
12026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ movq(rcx, Operand(rcx, 0));
12036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Check if it's the end of elements.
12056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ lea(rdx, FieldOperand(rbx,
12069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                               rax, times_pointer_size,
12076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               FixedArray::kHeaderSize - argc * kPointerSize));
12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ cmpq(rdx, rcx);
12096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(not_equal, &call_builtin);
12106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ addq(rcx, Immediate(kAllocationDelta * kPointerSize));
12116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ movq(kScratchRegister, new_space_allocation_limit);
12126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ cmpq(rcx, Operand(kScratchRegister, 0));
12136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(above, &call_builtin);
12146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // We fit and could grow elements.
12166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ movq(kScratchRegister, new_space_allocation_top);
12176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ movq(Operand(kScratchRegister, 0), rcx);
12186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ movq(rcx, Operand(rsp, argc * kPointerSize));
12196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Push the argument...
12216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ movq(Operand(rdx, 0), rcx);
12226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // ... and fill the rest with holes.
1223756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
12246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (int i = 1; i < kAllocationDelta; i++) {
12256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ movq(Operand(rdx, i * kPointerSize), kScratchRegister);
12266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
12276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Restore receiver to rdx as finish sequence assumes it's here.
12296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
12306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Increment element's and array's sizes.
12327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ SmiAddConstant(FieldOperand(rbx, FixedArray::kLengthOffset),
12337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        Smi::FromInt(kAllocationDelta));
1234756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
12359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      // Make new length a smi before returning it.
12369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      __ Integer32ToSmi(rax, rax);
12376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1238756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
12397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Elements are in new space, so write barrier is not required.
12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ ret((argc + 1) * kPointerSize);
12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1243756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ bind(&call_builtin);
12446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
12456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 argc + 1,
12466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 1);
12476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
1250bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object* obj = GenerateMissBranch();
1251bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (obj->IsFailure()) return obj;
12526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
125425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
12556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12586ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockObject* CallStubCompiler::CompileArrayPopCall(Object* object,
12596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                              JSObject* holder,
126059151504615d929945dc59db37bf1166937748c6Steve Block                                              JSGlobalPropertyCell* cell,
12616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                              JSFunction* function,
126259151504615d929945dc59db37bf1166937748c6Steve Block                                              String* name) {
12636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
1264756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  //  -- rcx                 : name
1265756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  //  -- rsp[0]              : return address
1266756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
12676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ...
1268756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  //  -- rsp[(argc + 1) * 8] : receiver
12696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
12706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If object is not an array, bail out to regular call.
127259151504615d929945dc59db37bf1166937748c6Steve Block  if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value();
12736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss, return_undefined, call_builtin;
12756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
12779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
12786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack.
12796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
12806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
12816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
12836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ JumpIfSmi(rdx, &miss);
12846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CheckPrototypes(JSObject::cast(object), rdx,
12866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  holder, rbx,
12873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                  rax, rdi, name, &miss);
12886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the elements array of the object.
12906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
12916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1292756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Check that the elements are in fast mode and writable.
1293756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
1294756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                 Heap::kFixedArrayMapRootIndex);
1295756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ j(not_equal, &call_builtin);
12966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the array's length into rcx and calculate new length.
12989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
12999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ subl(rcx, Immediate(1));
13006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(negative, &return_undefined);
13016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the last element.
1303756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ LoadRoot(r9, Heap::kTheHoleValueRootIndex);
13046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(rax, FieldOperand(rbx,
13059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                            rcx, times_pointer_size,
13066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            FixedArray::kHeaderSize));
13076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check if element is already the hole.
13086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmpq(rax, r9);
13099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // If so, call slow-case to also check prototypes for value.
13106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(equal, &call_builtin);
13116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set the array's length.
13139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
13146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Fill with the hole and return original value.
13166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(FieldOperand(rbx,
13179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                       rcx, times_pointer_size,
13186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       FixedArray::kHeaderSize),
13196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          r9);
13206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret((argc + 1) * kPointerSize);
13216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&return_undefined);
1323756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
13246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret((argc + 1) * kPointerSize);
13256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&call_builtin);
13276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop),
13286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               argc + 1,
13296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               1);
1330756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
13316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
1332bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object* obj = GenerateMissBranch();
1333bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (obj->IsFailure()) return obj;
13346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
133625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
13376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
13386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochObject* CallStubCompiler::CompileStringCharAtCall(Object* object,
13417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                  JSObject* holder,
134259151504615d929945dc59db37bf1166937748c6Steve Block                                                  JSGlobalPropertyCell* cell,
13437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                                  JSFunction* function,
134459151504615d929945dc59db37bf1166937748c6Steve Block                                                  String* name) {
134580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ----------- S t a t e -------------
134680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- rcx                 : function name
134780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- rsp[0]              : return address
134880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
134980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- ...
135080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- rsp[(argc + 1) * 8] : receiver
135180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // -----------------------------------
135280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
135380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If object is not a string, bail out to regular call.
135459151504615d929945dc59db37bf1166937748c6Steve Block  if (!object->IsString() || cell != NULL) return Heap::undefined_value();
135580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
135680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const int argc = arguments().immediate();
135780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
135880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label miss;
135980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label index_out_of_range;
136080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
136180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateNameCheck(name, &miss);
136280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
136380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the maps starting from the prototype haven't changed.
136480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateDirectLoadGlobalFunctionPrototype(masm(),
136580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                            Context::STRING_FUNCTION_INDEX,
13660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            rax,
13670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
136880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(object != holder);
136980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
137080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                  rbx, rdx, rdi, name, &miss);
137180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
137280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register receiver = rax;
137380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register index = rdi;
137480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register scratch1 = rbx;
137580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register scratch2 = rdx;
137680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register result = rax;
137780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
137880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (argc > 0) {
137980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movq(index, Operand(rsp, (argc - 0) * kPointerSize));
138080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
138180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
138280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
138380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
138480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  StringCharAtGenerator char_at_generator(receiver,
138580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          index,
138680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          scratch1,
138780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          scratch2,
138880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          result,
138980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          &miss,  // When not a string.
139080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          &miss,  // When not a number.
139180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          &index_out_of_range,
139280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          STRING_INDEX_IS_NUMBER);
139380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  char_at_generator.GenerateFast(masm());
139480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ret((argc + 1) * kPointerSize);
139580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
139680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ICRuntimeCallHelper call_helper;
139780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  char_at_generator.GenerateSlow(masm(), call_helper);
139880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
139980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&index_out_of_range);
140080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ LoadRoot(rax, Heap::kEmptyStringRootIndex);
140180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ret((argc + 1) * kPointerSize);
140280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
140380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&miss);
140480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Object* obj = GenerateMissBranch();
140580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (obj->IsFailure()) return obj;
140680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
140780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Return the generated code.
140880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return GetCode(function);
14097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
14107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
141259151504615d929945dc59db37bf1166937748c6Steve BlockObject* CallStubCompiler::CompileStringCharCodeAtCall(
141359151504615d929945dc59db37bf1166937748c6Steve Block    Object* object,
141459151504615d929945dc59db37bf1166937748c6Steve Block    JSObject* holder,
141559151504615d929945dc59db37bf1166937748c6Steve Block    JSGlobalPropertyCell* cell,
141659151504615d929945dc59db37bf1166937748c6Steve Block    JSFunction* function,
141759151504615d929945dc59db37bf1166937748c6Steve Block    String* name) {
141880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ----------- S t a t e -------------
141980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- rcx                 : function name
142080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- rsp[0]              : return address
142180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
142280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- ...
142380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- rsp[(argc + 1) * 8] : receiver
142480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // -----------------------------------
142580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
142680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If object is not a string, bail out to regular call.
142759151504615d929945dc59db37bf1166937748c6Steve Block  if (!object->IsString() || cell != NULL) return Heap::undefined_value();
142880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
142980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const int argc = arguments().immediate();
143080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
143180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label miss;
143280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label index_out_of_range;
143380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateNameCheck(name, &miss);
143480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
143580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the maps starting from the prototype haven't changed.
143680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateDirectLoadGlobalFunctionPrototype(masm(),
143780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                            Context::STRING_FUNCTION_INDEX,
14380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            rax,
14390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
144080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(object != holder);
144180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
144280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                  rbx, rdx, rdi, name, &miss);
144380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
144480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register receiver = rbx;
144580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register index = rdi;
144680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register scratch = rdx;
144780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register result = rax;
144880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
144980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (argc > 0) {
145080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ movq(index, Operand(rsp, (argc - 0) * kPointerSize));
145180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
145280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
145380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
145480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
145580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  StringCharCodeAtGenerator char_code_at_generator(receiver,
145680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   index,
145780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   scratch,
145880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   result,
145980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   &miss,  // When not a string.
146080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   &miss,  // When not a number.
146180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   &index_out_of_range,
146280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   STRING_INDEX_IS_NUMBER);
146380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  char_code_at_generator.GenerateFast(masm());
146480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ret((argc + 1) * kPointerSize);
146580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
146680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ICRuntimeCallHelper call_helper;
146780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  char_code_at_generator.GenerateSlow(masm(), call_helper);
146880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
146980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&index_out_of_range);
147080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ LoadRoot(rax, Heap::kNanValueRootIndex);
147180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ret((argc + 1) * kPointerSize);
14727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
147380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&miss);
147480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Object* obj = GenerateMissBranch();
147580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (obj->IsFailure()) return obj;
147680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
147780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Return the generated code.
147880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return GetCode(function);
147980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
14806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
148259151504615d929945dc59db37bf1166937748c6Steve BlockObject* CallStubCompiler::CompileStringFromCharCodeCall(
148359151504615d929945dc59db37bf1166937748c6Steve Block    Object* object,
148459151504615d929945dc59db37bf1166937748c6Steve Block    JSObject* holder,
148559151504615d929945dc59db37bf1166937748c6Steve Block    JSGlobalPropertyCell* cell,
148659151504615d929945dc59db37bf1166937748c6Steve Block    JSFunction* function,
148759151504615d929945dc59db37bf1166937748c6Steve Block    String* name) {
148859151504615d929945dc59db37bf1166937748c6Steve Block  // ----------- S t a t e -------------
148959151504615d929945dc59db37bf1166937748c6Steve Block  //  -- rcx                 : function name
149059151504615d929945dc59db37bf1166937748c6Steve Block  //  -- rsp[0]              : return address
149159151504615d929945dc59db37bf1166937748c6Steve Block  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
149259151504615d929945dc59db37bf1166937748c6Steve Block  //  -- ...
149359151504615d929945dc59db37bf1166937748c6Steve Block  //  -- rsp[(argc + 1) * 8] : receiver
149459151504615d929945dc59db37bf1166937748c6Steve Block  // -----------------------------------
149559151504615d929945dc59db37bf1166937748c6Steve Block
149659151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
149759151504615d929945dc59db37bf1166937748c6Steve Block
149859151504615d929945dc59db37bf1166937748c6Steve Block  // If the object is not a JSObject or we got an unexpected number of
149959151504615d929945dc59db37bf1166937748c6Steve Block  // arguments, bail out to the regular call.
150059151504615d929945dc59db37bf1166937748c6Steve Block  if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
150159151504615d929945dc59db37bf1166937748c6Steve Block
150259151504615d929945dc59db37bf1166937748c6Steve Block  Label miss;
150359151504615d929945dc59db37bf1166937748c6Steve Block  GenerateNameCheck(name, &miss);
150459151504615d929945dc59db37bf1166937748c6Steve Block
150559151504615d929945dc59db37bf1166937748c6Steve Block  if (cell == NULL) {
150659151504615d929945dc59db37bf1166937748c6Steve Block    __ movq(rdx, Operand(rsp, 2 * kPointerSize));
150759151504615d929945dc59db37bf1166937748c6Steve Block
150859151504615d929945dc59db37bf1166937748c6Steve Block    __ JumpIfSmi(rdx, &miss);
150959151504615d929945dc59db37bf1166937748c6Steve Block
151059151504615d929945dc59db37bf1166937748c6Steve Block    CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name,
151159151504615d929945dc59db37bf1166937748c6Steve Block                    &miss);
151259151504615d929945dc59db37bf1166937748c6Steve Block  } else {
151359151504615d929945dc59db37bf1166937748c6Steve Block    ASSERT(cell->value() == function);
151459151504615d929945dc59db37bf1166937748c6Steve Block    GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
151559151504615d929945dc59db37bf1166937748c6Steve Block    GenerateLoadFunctionFromCell(cell, function, &miss);
151659151504615d929945dc59db37bf1166937748c6Steve Block  }
151759151504615d929945dc59db37bf1166937748c6Steve Block
151859151504615d929945dc59db37bf1166937748c6Steve Block  // Load the char code argument.
151959151504615d929945dc59db37bf1166937748c6Steve Block  Register code = rbx;
152059151504615d929945dc59db37bf1166937748c6Steve Block  __ movq(code, Operand(rsp, 1 * kPointerSize));
152159151504615d929945dc59db37bf1166937748c6Steve Block
152259151504615d929945dc59db37bf1166937748c6Steve Block  // Check the code is a smi.
152359151504615d929945dc59db37bf1166937748c6Steve Block  Label slow;
152459151504615d929945dc59db37bf1166937748c6Steve Block  __ JumpIfNotSmi(code, &slow);
152559151504615d929945dc59db37bf1166937748c6Steve Block
152659151504615d929945dc59db37bf1166937748c6Steve Block  // Convert the smi code to uint16.
152759151504615d929945dc59db37bf1166937748c6Steve Block  __ SmiAndConstant(code, code, Smi::FromInt(0xffff));
152859151504615d929945dc59db37bf1166937748c6Steve Block
152959151504615d929945dc59db37bf1166937748c6Steve Block  StringCharFromCodeGenerator char_from_code_generator(code, rax);
153059151504615d929945dc59db37bf1166937748c6Steve Block  char_from_code_generator.GenerateFast(masm());
153159151504615d929945dc59db37bf1166937748c6Steve Block  __ ret(2 * kPointerSize);
153259151504615d929945dc59db37bf1166937748c6Steve Block
153359151504615d929945dc59db37bf1166937748c6Steve Block  ICRuntimeCallHelper call_helper;
153459151504615d929945dc59db37bf1166937748c6Steve Block  char_from_code_generator.GenerateSlow(masm(), call_helper);
153559151504615d929945dc59db37bf1166937748c6Steve Block
153659151504615d929945dc59db37bf1166937748c6Steve Block  // Tail call the full function. We do not have to patch the receiver
153759151504615d929945dc59db37bf1166937748c6Steve Block  // because the function makes no use of it.
153859151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&slow);
153959151504615d929945dc59db37bf1166937748c6Steve Block  __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
154059151504615d929945dc59db37bf1166937748c6Steve Block
154159151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&miss);
154259151504615d929945dc59db37bf1166937748c6Steve Block  // rcx: function name.
154359151504615d929945dc59db37bf1166937748c6Steve Block  Object* obj = GenerateMissBranch();
154459151504615d929945dc59db37bf1166937748c6Steve Block  if (obj->IsFailure()) return obj;
154559151504615d929945dc59db37bf1166937748c6Steve Block
154659151504615d929945dc59db37bf1166937748c6Steve Block  // Return the generated code.
154759151504615d929945dc59db37bf1166937748c6Steve Block  return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
154859151504615d929945dc59db37bf1166937748c6Steve Block}
154959151504615d929945dc59db37bf1166937748c6Steve Block
155059151504615d929945dc59db37bf1166937748c6Steve Block
15510d5e116f6aee03185f237311a943491bb079a768Kristian MonsenObject* CallStubCompiler::CompileMathFloorCall(Object* object,
15520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                               JSObject* holder,
15530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                               JSGlobalPropertyCell* cell,
15540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                               JSFunction* function,
15550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                               String* name) {
15560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // TODO(872): implement this.
15570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return Heap::undefined_value();
15580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
15590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
15600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1561402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 JSObject* holder,
1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 String* name) {
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1565402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rcx                 : function name
1566402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[0]              : return address
1567402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[8]              : argument argc
1568402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[16]             : argument argc - 1
1569402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ...
1570402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[argc * 8]       : argument 1
1571402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[(argc + 1) * 8] : argument 0 = receiver
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
15769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments.
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupResult lookup;
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallInterceptorCompiler compiler(this, arguments(), rcx);
15876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  compiler.Compile(masm(),
15886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   object,
15896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   holder,
15906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   name,
15916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   &lookup,
15926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   rdx,
15936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   rbx,
15946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   rdi,
15953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                   rax,
15966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   &miss);
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore receiver.
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(rax, &miss);
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy if
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary.
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rdi, rax);
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION);
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle load cache miss.
1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1619bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object* obj = GenerateMissBranch();
1620bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (obj->IsFailure()) return obj;
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            GlobalObject* holder,
1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            JSGlobalPropertyCell* cell,
1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            JSFunction* function,
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            String* name) {
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1633402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rcx                 : function name
1634402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[0]              : return address
1635402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[8]              : argument argc
1636402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[16]             : argument argc - 1
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ...
1638402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[argc * 8]       : argument 1
1639402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[(argc + 1) * 8] : argument 0 = receiver
164059151504615d929945dc59db37bf1166937748c6Steve Block  // -----------------------------------
164159151504615d929945dc59db37bf1166937748c6Steve Block
164259151504615d929945dc59db37bf1166937748c6Steve Block  SharedFunctionInfo* function_info = function->shared();
164359151504615d929945dc59db37bf1166937748c6Steve Block  if (function_info->HasCustomCallGenerator()) {
164459151504615d929945dc59db37bf1166937748c6Steve Block    const int id = function_info->custom_call_generator_id();
164559151504615d929945dc59db37bf1166937748c6Steve Block    Object* result = CompileCustomCall(
164659151504615d929945dc59db37bf1166937748c6Steve Block        id, object, holder, cell, function, name);
164759151504615d929945dc59db37bf1166937748c6Steve Block    // undefined means bail out to regular compiler.
164859151504615d929945dc59db37bf1166937748c6Steve Block    if (!result->IsUndefined()) return result;
164959151504615d929945dc59db37bf1166937748c6Steve Block  }
165059151504615d929945dc59db37bf1166937748c6Steve Block
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
16549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments.
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
165859151504615d929945dc59db37bf1166937748c6Steve Block  GenerateGlobalReceiverCheck(object, holder, name, &miss);
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
166059151504615d929945dc59db37bf1166937748c6Steve Block  GenerateLoadFunctionFromCell(cell, function, &miss);
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy.
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup the context (function already in edi).
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the cached code (tail call).
1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::call_global_inline, 1);
1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(function->is_compiled());
1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code(function->code());
1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(function->shared()->formal_parameter_count());
1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeCode(code, expected, arguments(),
1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                RelocInfo::CODE_TARGET, JUMP_FUNCTION);
1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::call_global_inline_miss, 1);
1682bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object* obj = GenerateMissBranch();
1683bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (obj->IsFailure()) return obj;
1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeObject* LoadStubCompiler::CompileLoadCallback(String* name,
1691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                              JSObject* object,
1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              JSObject* holder,
1693e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                              AccessorInfo* callback) {
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
16957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : receiver
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1701e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Failure* failure = Failure::InternalError();
17023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  bool success = GenerateLoadCallback(object, holder, rax, rcx, rbx, rdx, rdi,
1703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                      callback, name, &miss, &failure);
17040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!success) {
17050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    miss.Unuse();
17060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    return failure;
17070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
1708e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadConstant(JSObject* object,
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              JSObject* holder,
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              Object* value,
1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              String* name) {
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
17227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : receiver
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss);
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17376ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
17386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                 JSObject* object,
17396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                 JSObject* last) {
17406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
17417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : receiver
17426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rcx    : name
17436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[0] : return address
17446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
17456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
17466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Chech that receiver is not a smi.
17486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ JumpIfSmi(rax, &miss);
17496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the maps of the full prototype chain. Also check that
17516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // global property cells up to (but not including) the last object
17526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in the prototype chain are empty.
17533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss);
17546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If the last object in the prototype chain is a global object,
17566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // check that the global property cell is empty.
17576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (last->IsGlobalObject()) {
17586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* cell = GenerateCheckPropertyCell(masm(),
17596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             GlobalObject::cast(last),
17606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             name,
17616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             rdx,
17626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             &miss);
17630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (cell->IsFailure()) {
17640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      miss.Unuse();
17650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      return cell;
17660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
17676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
17686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return undefined if maps of the full prototype chain are still the
17706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // same and no global property with this name contains a value.
17716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
17726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret(0);
17736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
17756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
17766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
17786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return GetCode(NONEXISTENT, Heap::empty_string());
17796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadField(JSObject* object,
1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           JSObject* holder,
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           int index,
1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           String* name) {
1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
17877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : receiver
1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(object, holder, rax, rbx, rdx, rdi, index, name, &miss);
1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 JSObject* holder,
1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 String* name) {
1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
18067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : receiver
1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
1809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupResult lookup;
1813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(368): Compile in the whole chain: all the interceptors in
1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototypes and ultimate answer.
1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadInterceptor(receiver,
1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          holder,
1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &lookup,
1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          rax,
1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          rcx,
1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          rdx,
1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          rbx,
18243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                          rdi,
1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          name,
1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &miss);
1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            GlobalObject* holder,
1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            JSGlobalPropertyCell* cell,
1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            String* name,
1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            bool is_dont_delete) {
1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
18427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : receiver
1843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the object is the holder then we know that it's a global
1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object which can only happen for contextual loads. In this case,
1850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the receiver cannot be a smi.
1851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object != holder) {
1852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ JumpIfSmi(rax, &miss);
1853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
18563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, rax, holder, rbx, rdx, rdi, name, &miss);
1857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value from the cell.
18597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Move(rbx, Handle<JSGlobalPropertyCell>(cell));
18607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
1861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for deleted property if property can actually be deleted.
1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!is_dont_delete) {
18647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ j(equal, &miss);
1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (FLAG_debug_code) {
18677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Check(not_equal, "DontDelete cells can't contain the hole");
1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ IncrementCounter(&Counters::named_load_global_stub, 1);
18727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ movq(rax, rbx);
1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
18760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ IncrementCounter(&Counters::named_load_global_stub_miss, 1);
1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   JSObject* receiver,
1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   JSObject* holder,
1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   AccessorInfo* callback) {
1888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
18897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax     : key
18907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rdx     : receiver
1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0]  : return address
1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::keyed_load_callback, 1);
1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Cmp(rax, Handle<String>(name));
1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1901e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Failure* failure = Failure::InternalError();
19023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  bool success = GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx, rdi,
1903e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                      callback, name, &miss, &failure);
19040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!success) {
19050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    miss.Unuse();
19060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    return failure;
19070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
1908e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ DecrementCounter(&Counters::keyed_load_callback, 1);
1911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
1919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
19207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : key
19217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rdx    : receiver
1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0]  : return address
1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::keyed_load_array_length, 1);
1927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Cmp(rax, Handle<String>(name));
1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
1931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateLoadArrayLength(masm(), rdx, rcx, &miss);
1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ DecrementCounter(&Counters::keyed_load_array_length, 1);
1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
1939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
1943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   JSObject* receiver,
1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   JSObject* holder,
1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   Object* value) {
1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
19477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : key
19487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rdx    : receiver
1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0]  : return address
1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::keyed_load_constant_function, 1);
1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
1956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Cmp(rax, Handle<String>(name));
1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadConstant(receiver, holder, rdx, rbx, rcx, rdi,
1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       value, name, &miss);
1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
19727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : key
19737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rdx    : receiver
1974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0]  : return address
1975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
1979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
1981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Cmp(rax, Handle<String>(name));
1982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
1985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
1987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
1991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                      JSObject* holder,
1996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                      String* name) {
1997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
19987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : key
19997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rdx    : receiver
2000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0]  : return address
2001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::keyed_load_interceptor, 1);
2005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
2007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Cmp(rax, Handle<String>(name));
2008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
2009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupResult lookup;
2011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
2012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadInterceptor(receiver,
2013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          holder,
2014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &lookup,
2015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          rdx,
20167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                          rax,
20177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                          rcx,
2018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          rbx,
20193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                          rdi,
2020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          name,
2021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &miss);
2022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ DecrementCounter(&Counters::keyed_load_interceptor, 1);
2024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
2032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
20337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : key
20347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rdx    : receiver
20357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rsp[0] : return address
2036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::keyed_load_string_length, 1);
2040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
2042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Cmp(rax, Handle<String>(name));
2043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
2044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss);
2046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ DecrementCounter(&Counters::keyed_load_string_length, 1);
2048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreCallback(JSObject* object,
2056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                AccessorInfo* callback,
2057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                String* name) {
2058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax    : value
2060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
20614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- rdx    : receiver
2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
2063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
20674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ JumpIfSmi(rdx, &miss);
2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
20704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Handle<Map>(object->map()));
2072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
20764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ CheckAccessGlobalProxy(rdx, rbx, &miss);
2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(rbx);  // remove the return address
20844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(rdx);  // receiver
2085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Push(Handle<AccessorInfo>(callback));  // callback info
2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rcx);  // name
2087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rax);  // value
2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rbx);  // restore return address
2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_callback_property =
2092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
20936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(store_callback_property, 4, 1);
2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreField(JSObject* object,
2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             int index,
2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Map* transition,
2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             String* name) {
2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax    : value
2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
21124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- rdx    : receiver
2113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2117402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Generate store field code.  Preserves receiver and name on jump to miss.
2118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateStoreField(masm(),
2119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     object,
2120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     index,
2121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     transition,
21224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                     rdx, rcx, rbx,
2123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     &miss);
2124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
2128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
2132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
2136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   String* name) {
2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax    : value
2139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
21404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- rdx    : receiver
2141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
21464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ JumpIfSmi(rdx, &miss);
2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
21494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Handle<Map>(receiver->map()));
2151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
2152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (receiver->IsJSGlobalProxy()) {
21554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ CheckAccessGlobalProxy(rdx, rbx, &miss);
2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(rbx);  // remove the return address
21634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(rdx);  // receiver
2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rcx);  // name
2165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rax);  // value
2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rbx);  // restore return address
2167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_ic_property =
2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
21716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(store_ic_property, 3, 1);
2172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
2176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              JSGlobalPropertyCell* cell,
2185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              String* name) {
2186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax    : value
2188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
21894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- rdx    : receiver
2190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
2191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
21954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Handle<Map>(object->map()));
2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
2198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Store the value in the cell.
2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Move(rcx, Handle<JSGlobalPropertyCell>(cell));
2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(FieldOperand(rcx, JSGlobalPropertyCell::kValueOffset), rax);
2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the value (register rax).
2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::named_store_global_inline, 1);
2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::named_store_global_inline_miss, 1);
2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadField(String* name,
2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                JSObject* receiver,
2220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                JSObject* holder,
2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                int index) {
2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
22237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax     : key
22247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rdx     : receiver
22257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rsp[0]  : return address
2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::keyed_load_field, 1);
2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Cmp(rax, Handle<String>(name));
2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
2234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(receiver, holder, rdx, rbx, rcx, rdi, index, name, &miss);
2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ DecrementCounter(&Counters::keyed_load_field, 1);
2239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  int index,
2248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  Map* transition,
2249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  String* name) {
2250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax     : value
2252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- rcx     : key
2253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- rdx     : receiver
2254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0]  : return address
2255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::keyed_store_field, 1);
2259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
2261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Cmp(rcx, Handle<String>(name));
2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
2263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2264402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Generate store field code.  Preserves receiver and name on jump to miss.
2265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateStoreField(masm(),
2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     object,
2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     index,
2268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     transition,
2269402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                     rdx, rcx, rbx,
2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     &miss);
2271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ DecrementCounter(&Counters::keyed_store_field, 1);
2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadInterceptor(JSObject* object,
22847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           JSObject* interceptor_holder,
2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           LookupResult* lookup,
2286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register name_reg,
2288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch1,
2289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch2,
22903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                           Register scratch3,
2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           String* name,
2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss) {
22937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(interceptor_holder->HasNamedInterceptor());
22947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
22957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
22967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the receiver isn't a smi.
22977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ JumpIfSmi(receiver, miss);
22987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
22997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // So far the most popular follow ups for interceptor loads are FIELD
23007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // and CALLBACKS, so inline only them, other cases may be added
23017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // later.
23027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  bool compile_followup_inline = false;
23037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (lookup->IsProperty() && lookup->IsCacheable()) {
23047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == FIELD) {
23057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      compile_followup_inline = true;
23067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else if (lookup->type() == CALLBACKS &&
23077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        lookup->GetCallbackObject()->IsAccessorInfo() &&
23087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) {
23097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      compile_followup_inline = true;
23107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
23117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
23127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (compile_followup_inline) {
23147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Compile the interceptor call, followed by inline code to load the
23157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // property from further up the prototype chain if the call fails.
23167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps haven't changed.
23177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
23183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          scratch1, scratch2, scratch3,
23193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          name, miss);
23207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
23217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Save necessary data before invoking an interceptor.
23237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Requires a frame to make GC aware of pushed pointers.
23247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ EnterInternalFrame();
23257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
23277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // CALLBACKS case needs a receiver to be passed into C++ callback.
23287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(receiver);
23297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
23307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ push(holder_reg);
23317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ push(name_reg);
23327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Invoke an interceptor.  Note: map checks from receiver to
23347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // interceptor's holder has been compiled before (see a caller
23357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // of this method.)
23367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    CompileCallLoadPropertyWithInterceptor(masm(),
23377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           receiver,
23387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           holder_reg,
23397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           name_reg,
23407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           interceptor_holder);
23417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check if interceptor provided a value for property.  If it's
23437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // the case, return immediately.
23447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Label interceptor_failed;
23457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
23467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ j(equal, &interceptor_failed);
23477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ LeaveInternalFrame();
23487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ ret(0);
23497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ bind(&interceptor_failed);
23517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ pop(name_reg);
23527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ pop(holder_reg);
23537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
23547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ pop(receiver);
23557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
23567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ LeaveInternalFrame();
23587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps from interceptor's holder to lookup's holder
23607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // haven't changed.  And load lookup's holder into |holder| register.
23617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (interceptor_holder != lookup->holder()) {
23627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      holder_reg = CheckPrototypes(interceptor_holder,
23637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   holder_reg,
23647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   lookup->holder(),
23657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch1,
23667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch2,
23673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                   scratch3,
23687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   name,
23697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   miss);
23707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
23717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == FIELD) {
23737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found FIELD property in prototype chain of interceptor's holder.
23747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Retrieve a field from field's holder.
23757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      GenerateFastPropertyLoad(masm(), rax, holder_reg,
23767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                               lookup->holder(), lookup->GetFieldIndex());
23777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ ret(0);
23787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
23797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found CALLBACKS property in prototype chain of interceptor's
23807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // holder.
23817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(lookup->type() == CALLBACKS);
23827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
23837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
23847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(callback != NULL);
23857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(callback->getter() != NULL);
23867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Tail call to runtime.
23887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Important invariant in CALLBACKS case: the code above must be
23897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // structured to never clobber |receiver| register.
23907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ pop(scratch2);  // return address
23917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(receiver);
23927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(holder_reg);
23937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ Move(holder_reg, Handle<AccessorInfo>(callback));
23947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(holder_reg);
23957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
23967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(name_reg);
23977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(scratch2);  // restore return address
23987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
23997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ExternalReference ref =
24007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
24017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ TailCallExternalReference(ref, 5, 1);
24027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
24037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {  // !compile_followup_inline
24047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Call the runtime system to load the interceptor.
24057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps haven't changed.
24067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
24073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          scratch1, scratch2, scratch3,
24083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          name, miss);
24097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ pop(scratch2);  // save old return address
24107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    PushInterceptorArguments(masm(), receiver, holder_reg,
24117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                             name_reg, interceptor_holder);
24127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ push(scratch2);  // restore old return address
24137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
24147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ExternalReference ref = ExternalReference(
24157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
24167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ TailCallExternalReference(ref, 5, 1);
24177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkebool StubCompiler::GenerateLoadCallback(JSObject* object,
2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        JSObject* holder,
2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register receiver,
2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register name_reg,
2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch1,
2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch2,
24273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                        Register scratch3,
2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AccessorInfo* callback,
2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        String* name,
2430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Label* miss,
2431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Failure** failure) {
2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(receiver, miss);
2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register reg =
2437bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      CheckPrototypes(object, receiver, holder, scratch1,
2438bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                      scratch2, scratch3, name, miss);
2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2440bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Handle<AccessorInfo> callback_handle(callback);
2441bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2442bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ EnterInternalFrame();
2443bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ PushHandleScope(scratch2);
2444bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Push the stack address where the list of arguments ends.
2445bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(scratch2, rsp);
2446bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ subq(scratch2, Immediate(2 * kPointerSize));
2447bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(scratch2);
2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(receiver);  // receiver
2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(reg);  // holder
2450bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (Heap::InNewSpace(callback_handle->data())) {
2451bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ Move(scratch2, callback_handle);
2452bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ push(FieldOperand(scratch2, AccessorInfo::kDataOffset));  // data
2453bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  } else {
2454bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    __ Push(Handle<Object>(callback_handle->data()));
2455bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(name_reg);  // name
2457bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Save a pointer to where we pushed the arguments pointer.
2458bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // This will be passed as the const AccessorInfo& to the C++ callback.
2459bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2460bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch#ifdef _WIN64
2461bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Win64 uses first register--rcx--for returned value.
2462bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register accessor_info_arg = r8;
2463bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register name_arg = rdx;
2464bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch#else
2465bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register accessor_info_arg = rdx;  // temporary, copied to rsi by the stub.
2466bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register name_arg = rdi;
2467bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch#endif
2468bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2469bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(accessor_info_arg, rsp);
2470bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ addq(accessor_info_arg, Immediate(4 * kPointerSize));
2471bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(name_arg, rsp);
2472bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2473bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Do call through the api.
2474bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT_EQ(5, ApiGetterEntryStub::kStackSpace);
2475bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Address getter_address = v8::ToCData<Address>(callback->getter());
2476bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ApiFunction fun(getter_address);
2477bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ApiGetterEntryStub stub(callback_handle, &fun);
2478bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch#ifdef _WIN64
2479bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // We need to prepare a slot for result handle on stack and put
2480bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // a pointer to it into 1st arg register.
2481bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ push(Immediate(0));
2482bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(rcx, rsp);
2483bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch#endif
2484bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Emitting a stub call may try to allocate (if the code is not
2485bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // already generated).  Do not allow the assembler to perform a
2486bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // garbage collection but instead return the allocation failure
2487bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // object.
2488bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object* result = masm()->TryCallStub(&stub);
2489bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (result->IsFailure()) {
2490bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    *failure = Failure::cast(result);
2491bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    return false;
2492bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
2493bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch#ifdef _WIN64
2494bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Discard allocated slot.
2495bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ addq(rsp, Immediate(kPointerSize));
2496bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch#endif
2497bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
2498bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // We need to avoid using rax since that now holds the result.
2499bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Register tmp = scratch2.is(rax) ? reg : scratch2;
2500bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Emitting PopHandleScope may try to allocate.  Do not allow the
2501bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // assembler to perform a garbage collection but instead return a
2502bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // failure object.
2503bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  result = masm()->TryPopHandleScope(rax, tmp);
2504bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  if (result->IsFailure()) {
2505bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    *failure = Failure::cast(result);
2506bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    return false;
2507bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
2508bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ LeaveInternalFrame();
2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2510bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ret(0);
2511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return true;
2513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister StubCompiler::CheckPrototypes(JSObject* object,
2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register object_reg,
2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       JSObject* holder,
2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register holder_reg,
25203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Register scratch1,
25213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Register scratch2,
2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       String* name,
2523402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                       int save_at_depth,
25243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Label* miss) {
25253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Make sure there's no overlap between holder and object registers.
25263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
25273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
25283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch         && !scratch2.is(scratch1));
25293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Keep track of the current object in register reg.  On the first
25313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // iteration, reg is an alias for object_reg, on later iterations,
25323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // it is an alias for holder_reg.
25333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register reg = object_reg;
25343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  int depth = 0;
25353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (save_at_depth == depth) {
25373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ movq(Operand(rsp, kPointerSize), object_reg);
25383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
25393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check the maps in the prototype chain.
25413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Traverse the prototype chain from the object and do map checks.
25423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  JSObject* current = object;
25433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  while (current != holder) {
25443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    depth++;
25453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Only global objects and objects that do not require access
25473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // checks are allowed in stubs.
25483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
25493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    JSObject* prototype = JSObject::cast(current->GetPrototype());
25513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    if (!current->HasFastProperties() &&
25523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        !current->IsJSGlobalObject() &&
25533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        !current->IsJSGlobalProxy()) {
25543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      if (!name->IsSymbol()) {
25553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        Object* lookup_result = Heap::LookupSymbol(name);
25563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        if (lookup_result->IsFailure()) {
25573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch          set_failure(Failure::cast(lookup_result));
25583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch          return reg;
25593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        } else {
25603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch          name = String::cast(lookup_result);
25613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        }
25623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      }
25633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      ASSERT(current->property_dictionary()->FindEntry(name) ==
25643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch             StringDictionary::kNotFound);
25653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      GenerateDictionaryNegativeLookup(masm(),
25673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       miss,
25683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       reg,
25693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       name,
25703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       scratch1,
25713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       scratch2);
25723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
25733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      reg = holder_reg;  // from now the object is in holder_reg
25743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
25753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    } else if (Heap::InNewSpace(prototype)) {
25763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Get the map of the current object.
25773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
25783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ Cmp(scratch1, Handle<Map>(current->map()));
25793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Branch on the result of the map check.
25803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ j(not_equal, miss);
25813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Check access rights to the global object.  This has to happen
25823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // after the map check so that we know that the object is
25833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // actually a global object.
25843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      if (current->IsJSGlobalProxy()) {
25853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        __ CheckAccessGlobalProxy(reg, scratch1, miss);
25863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        // Restore scratch register to be the map of the object.
25883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        // We load the prototype from the map in the scratch register.
25893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
25903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      }
25913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // The prototype is in new space; we cannot store a reference
25923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // to it in the code. Load it from the map.
25933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      reg = holder_reg;  // from now the object is in holder_reg
25943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
25953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
25963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    } else {
25973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Check the map of the current object.
25983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ Cmp(FieldOperand(reg, HeapObject::kMapOffset),
25993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch          Handle<Map>(current->map()));
26003bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Branch on the result of the map check.
26013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ j(not_equal, miss);
26023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Check access rights to the global object.  This has to happen
26033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // after the map check so that we know that the object is
26043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // actually a global object.
26053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      if (current->IsJSGlobalProxy()) {
26063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        __ CheckAccessGlobalProxy(reg, scratch1, miss);
26073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      }
26083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // The prototype is in old space; load it directly.
26093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      reg = holder_reg;  // from now the object is in holder_reg
26103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ Move(reg, Handle<JSObject>(prototype));
26113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    }
26123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    if (save_at_depth == depth) {
26143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ movq(Operand(rsp, kPointerSize), reg);
26153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    }
26163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Go to the next object in the prototype chain.
26183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    current = prototype;
26193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
26203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check the holder map.
26223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map()));
26233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ j(not_equal, miss);
26243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Log the check depth.
26263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  LOG(IntEvent("check-maps-depth", depth + 1));
26273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
26283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Perform security check for access to the global object and return
26293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // the holder register.
26303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(current == holder);
26313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
26323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (current->IsJSGlobalProxy()) {
26333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ CheckAccessGlobalProxy(reg, scratch1, miss);
26343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we've skipped any global objects, it's not enough to verify
26376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // that their maps haven't changed.  We also need to check that the
26386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // property cell for the property is still empty.
26393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  current = object;
26403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  while (current != holder) {
26413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    if (current->IsGlobalObject()) {
26426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Object* cell = GenerateCheckPropertyCell(masm(),
26433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                               GlobalObject::cast(current),
26446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               name,
26453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                               scratch1,
26466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                               miss);
26476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (cell->IsFailure()) {
26486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        set_failure(Failure::cast(cell));
26493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        return reg;
2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
26523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    current = JSObject::cast(current->GetPrototype());
2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the register containing the holder.
26563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  return reg;
2657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadField(JSObject* object,
2661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     JSObject* holder,
2662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register receiver,
2663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch1,
2664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch2,
26653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                     Register scratch3,
2666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     int index,
2667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     String* name,
2668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Label* miss) {
2669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(receiver, miss);
2671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the prototype chain.
2673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register reg =
2674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckPrototypes(object, receiver, holder,
26753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                      scratch1, scratch2, scratch3, name, miss);
2676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value from the properties.
2678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), rax, reg, holder, index);
2679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
2680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadConstant(JSObject* object,
2684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        JSObject* holder,
2685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register receiver,
2686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch1,
2687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch2,
26883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                        Register scratch3,
2689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Object* value,
2690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        String* name,
2691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* miss) {
2692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(receiver, miss);
2694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
2696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register reg =
2697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckPrototypes(object, receiver, holder,
26983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                      scratch1, scratch2, scratch3, name, miss);
2699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the constant value.
2701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Move(rax, Handle<Object>(value));
2702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
2703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Specialized stub for constructing objects from functions which only have only
2707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// simple assignments of the form this.x = ...; in their body.
2708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* ConstructStubCompiler::CompileConstructStub(
2709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SharedFunctionInfo* shared) {
2710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax : argc
2712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rdi : constructor
2713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
2714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[4] : last argument
2715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_stub_call;
2717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use r8 for holding undefined which is used in several places below.
2719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Move(r8, Factory::undefined_value());
2720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check to see whether there are any break points in the function code. If
2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // there are jump to the generic constructor stub which calls the actual
2724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code for the function thereby hitting the break points.
2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kDebugInfoOffset));
2727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmpq(rbx, r8);
2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &generic_stub_call);
2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map and verify that it is in fact a map.
2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Will both indicate a NULL and a Smi.
2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kSmiTag == 0);
2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(rbx, &generic_stub_call);
2736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(rbx, MAP_TYPE, rcx);
2737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &generic_stub_call);
2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cannot construct functions this way.
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdi: constructor
2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rbx: initial map
2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpInstanceType(rbx, JS_FUNCTION_TYPE);
2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Assert(not_equal, "Function constructed by construct stub.");
2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Now allocate the JSObject in new space.
2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdi: constructor
2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rbx: initial map
2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movzxbq(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset));
2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ shl(rcx, Immediate(kPointerSizeLog2));
2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ AllocateInNewSpace(rcx,
2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        rdx,
2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        rcx,
2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        no_reg,
2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        &generic_stub_call,
2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        NO_ALLOCATION_FLAGS);
2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSObject, now initialize the fields and add the heap tag.
2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rbx: initial map
2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdx: JSObject (untagged)
2762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(Operand(rdx, JSObject::kMapOffset), rbx);
2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Move(rbx, Factory::empty_fixed_array());
2764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(Operand(rdx, JSObject::kPropertiesOffset), rbx);
2765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(Operand(rdx, JSObject::kElementsOffset), rbx);
2766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: argc
2768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdx: JSObject (untagged)
2769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the address of the first in-object property into r9.
2770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(r9, Operand(rdx, JSObject::kHeaderSize));
2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the first argument. The stack contains only the
2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // return address on top of the argc arguments.
2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(rcx, Operand(rsp, rax, times_pointer_size, 0));
2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: argc
2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rcx: first argument
2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdx: JSObject (untagged)
2778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r8: undefined
2779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r9: first in-object property of the JSObject
2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the initialized properties with a constant value or a passed argument
2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // depending on the this.x = ...; assignment in the function.
2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (shared->IsThisPropertyAssignmentArgument(i)) {
2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check if the argument assigned to the property is actually passed.
2785e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // If argument is not passed the property is set to undefined,
2786e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // otherwise find it on the stack.
2787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int arg_number = shared->GetThisPropertyAssignmentArgument(i);
2788e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ movq(rbx, r8);
2789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmpq(rax, Immediate(arg_number));
2790e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ cmovq(above, rbx, Operand(rcx, arg_number * -kPointerSize));
2791e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Store value in the property.
2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ movq(Operand(r9, i * kPointerSize), rbx);
2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to the constant value.
2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ Move(Operand(r9, i * kPointerSize), constant);
2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the unused in-object property fields with undefined.
2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = shared->this_property_assignments_count();
2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       i < shared->CalculateInObjectProperties();
2803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       i++) {
2804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ movq(Operand(r9, i * kPointerSize), r8);
2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: argc
2808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdx: JSObject (untagged)
2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move argc to rbx and the JSObject to return to rax and tag it.
2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rbx, rax);
2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rax, rdx);
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ or_(rax, Immediate(kHeapObjectTag));
2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: JSObject
2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rbx: argc
2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack and return.
2817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(rcx);
2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(rsp, Operand(rsp, rbx, times_pointer_size, 1 * kPointerSize));
2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rcx);
2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::constructed_objects, 1);
2821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::constructed_objects_stub, 1);
2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic stub in case the specialized code cannot handle the
2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // construction.
2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_stub_call);
2827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
2828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> generic_construct_stub(code);
2829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
2830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode();
2833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
2839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
2841