1f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com// Copyright 2012 the V8 project authors. All rights reserved.
25ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// Redistribution and use in source and binary forms, with or without
35ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// modification, are permitted provided that the following conditions are
45ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// met:
55ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//
65ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//     * Redistributions of source code must retain the above copyright
75ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       notice, this list of conditions and the following disclaimer.
85ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//     * Redistributions in binary form must reproduce the above
95ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       copyright notice, this list of conditions and the following
105ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       disclaimer in the documentation and/or other materials provided
115ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       with the distribution.
125ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//     * Neither the name of Google Inc. nor the names of its
135ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       contributors may be used to endorse or promote products derived
145ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       from this software without specific prior written permission.
155ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//
165ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org
285aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org#include "v8.h"
295aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
3093a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_X64
319dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
324a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org#include "arguments.h"
335aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org#include "ic-inl.h"
3444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include "codegen.h"
355aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org#include "stub-cache.h"
365aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
375aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.orgnamespace v8 {
385aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.orgnamespace internal {
395aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
400b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org#define __ ACCESS_MASM(masm)
410b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
420b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
43ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgstatic void ProbeTable(Isolate* isolate,
44ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                       MacroAssembler* masm,
450b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                       Code::Flags flags,
460b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                       StubCache::Table table,
47812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org                       Register receiver,
480b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                       Register name,
49812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org                       // The offset is scaled by 4, based on
50812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org                       // kHeapObjectTagSize, which is two bits
510b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                       Register offset) {
52812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // We need to scale up the pointer by 2 because the offset is scaled by less
53812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // than the pointer size.
54812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  ASSERT(kPointerSizeLog2 == kHeapObjectTagSize + 1);
55812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  ScaleFactor scale_factor = times_2;
56812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
571510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ASSERT_EQ(3 * kPointerSize, sizeof(StubCache::Entry));
589d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // The offset register holds the entry offset times four (due to masking
599d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // and shifting optimizations).
60ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
61812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
620b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  Label miss;
630b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
64812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // Multiply by 3 because there are 3 fields per entry (name, code, map).
65812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  __ lea(offset, Operand(offset, offset, times_2, 0));
66812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
67ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ LoadAddress(kScratchRegister, key_offset);
68812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
690b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Check that the key in the entry matches the name.
709d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // Multiply entry offset by 16 to get the entry address. Since the
719d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // offset register already holds the entry offset times four, multiply
729d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  // by a further four.
73812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  __ cmpl(name, Operand(kScratchRegister, offset, scale_factor, 0));
74812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  __ j(not_equal, &miss);
75812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
76812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // Get the map entry from the cache.
77812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // Use key_offset + kPointerSize * 2, rather than loading map_offset.
78812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  __ movq(kScratchRegister,
79812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org          Operand(kScratchRegister, offset, scale_factor, kPointerSize * 2));
80812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  __ cmpq(kScratchRegister, FieldOperand(receiver, HeapObject::kMapOffset));
810b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ j(not_equal, &miss);
82812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
830b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Get the code entry from the cache.
84812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  __ LoadAddress(kScratchRegister, value_offset);
850b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ movq(kScratchRegister,
86812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org          Operand(kScratchRegister, offset, scale_factor, 0));
87812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
880b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Check that the flags match what we're looking for.
890b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ movl(offset, FieldOperand(kScratchRegister, Code::kFlagsOffset));
900b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ and_(offset, Immediate(~Code::kFlagsNotUsedInLookup));
910b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ cmpl(offset, Immediate(flags));
920b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ j(not_equal, &miss);
930b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
94812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org#ifdef DEBUG
95812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
96812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      __ jmp(&miss);
97812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
98812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      __ jmp(&miss);
99812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    }
100812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org#endif
101812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1020b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Jump to the first instruction in the code stub.
1030b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ addq(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag));
1040b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ jmp(kScratchRegister);
1050b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
1060b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ bind(&miss);
1070b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org}
1080b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
1090b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
110057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.orgvoid StubCompiler::GenerateDictionaryNegativeLookup(MacroAssembler* masm,
111057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Label* miss_label,
112057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Register receiver,
113057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Handle<Name> name,
114057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Register scratch0,
115057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Register scratch1) {
116750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  ASSERT(name->IsUniqueName());
117057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  ASSERT(!receiver.is(scratch0));
118394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Counters* counters = masm->isolate()->counters();
119394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ IncrementCounter(counters->negative_lookups(), 1);
120394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ IncrementCounter(counters->negative_lookups_miss(), 1);
121394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
122057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  __ movq(scratch0, FieldOperand(receiver, HeapObject::kMapOffset));
123394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
124394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  const int kInterceptorOrAccessCheckNeededMask =
125394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
126394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
127394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Bail out if the receiver has a named interceptor or requires access checks.
128057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  __ testb(FieldOperand(scratch0, Map::kBitFieldOffset),
129394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com           Immediate(kInterceptorOrAccessCheckNeededMask));
130394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ j(not_zero, miss_label);
131394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
132394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Check that receiver is a JSObject.
133057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  __ CmpInstanceType(scratch0, FIRST_SPEC_OBJECT_TYPE);
134394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ j(below, miss_label);
135394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
136394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Load properties array.
137057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  Register properties = scratch0;
138394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
139394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
140394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Check that the properties array is a dictionary.
141394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset),
142394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                 Heap::kHashTableMapRootIndex);
143394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ j(not_equal, miss_label);
144394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
145394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Label done;
146750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  NameDictionaryLookupStub::GenerateNegativeLookup(masm,
147750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                   miss_label,
148750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                   &done,
149750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                   properties,
150750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                   name,
151057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                   scratch1);
152394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ bind(&done);
153394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ DecrementCounter(counters->negative_lookups_miss(), 1);
154394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
155394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
156394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1570b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.orgvoid StubCache::GenerateProbe(MacroAssembler* masm,
1580b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                              Code::Flags flags,
1590b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                              Register receiver,
1600b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                              Register name,
1610b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                              Register scratch,
162e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org                              Register extra,
163812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org                              Register extra2,
164812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org                              Register extra3) {
1657979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Isolate* isolate = masm->isolate();
1660b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  Label miss;
167e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  USE(extra);   // The register extra is not used on the X64 platform.
168e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  USE(extra2);  // The register extra2 is not used on the X64 platform.
169812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  USE(extra3);  // The register extra2 is not used on the X64 platform.
170812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // Make sure that code is valid. The multiplying code relies on the
1711510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // entry size being 3 * kPointerSize.
1721510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ASSERT(sizeof(Entry) == 3 * kPointerSize);
1730b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
1740b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Make sure the flags do not name a specific type.
1750b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
1760b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
1770b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Make sure that there are no register conflicts.
1780b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  ASSERT(!scratch.is(receiver));
1790b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  ASSERT(!scratch.is(name));
1800b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
181e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  // Check scratch register is valid, extra and extra2 are unused.
182e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  ASSERT(!scratch.is(no_reg));
183e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  ASSERT(extra2.is(no_reg));
184812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  ASSERT(extra3.is(no_reg));
185812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
186812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Counters* counters = masm->isolate()->counters();
187812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1);
188e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org
1890b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Check that the receiver isn't a smi.
1904af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  __ JumpIfSmi(receiver, &miss);
1910b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
1920b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Get the map of the receiver and compute the hash.
193750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  __ movl(scratch, FieldOperand(name, Name::kHashFieldOffset));
1940b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Use only the low 32 bits of the map pointer.
1950b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
1960b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ xor_(scratch, Immediate(flags));
197812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // We mask out the last two bits because they are not part of the hash and
198812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // they are always 01 for maps.  Also in the two 'and' instructions below.
1990b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
2000b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2010b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Probe the primary table.
202812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch);
2030b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2040b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Primary miss: Compute hash for secondary probe.
205750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  __ movl(scratch, FieldOperand(name, Name::kHashFieldOffset));
2060b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
2070b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ xor_(scratch, Immediate(flags));
2080b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
2090b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ subl(scratch, name);
2100b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ addl(scratch, Immediate(flags));
2110b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ and_(scratch, Immediate((kSecondaryTableSize - 1) << kHeapObjectTagSize));
2120b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2130b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Probe the secondary table.
214812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch);
2150b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2160b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Cache miss: Fall-through and let caller handle the miss by
2170b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // entering the runtime system.
2180b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ bind(&miss);
219812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1);
2200b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org}
2210b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2220b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2235d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.orgvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
2245d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                                                       int index,
2255d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                                                       Register prototype) {
2265d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Load the global or builtins object from the current context.
2275d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ movq(prototype,
22846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org          Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
22946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the native context from the global or builtins object.
2305d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ movq(prototype,
23146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org          FieldOperand(prototype, GlobalObject::kNativeContextOffset));
23246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the function from the native context.
2335d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ movq(prototype, Operand(prototype, Context::SlotOffset(index)));
2345d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Load the initial map.  The global functions all have initial maps.
2355d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ movq(prototype,
23646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org          FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
2375d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Load the prototype from the initial map.
2385d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
2395d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org}
2400b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2410b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2425d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.orgvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
243c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    MacroAssembler* masm,
244c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    int index,
245c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Register prototype,
246c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Label* miss) {
2477979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Isolate* isolate = masm->isolate();
2485d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Check we're still in the same context.
24946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ Move(prototype, isolate->global_object());
25046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ cmpq(Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)),
2515d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org          prototype);
2525d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ j(not_equal, miss);
2535d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Get the global function with the given index.
254c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Handle<JSFunction> function(
25546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      JSFunction::cast(isolate->native_context()->get(index)));
2565d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Load its initial map. The global functions all have initial maps.
2575d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ Move(prototype, Handle<Map>(function->initial_map()));
2585d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Load the prototype from the initial map.
2595d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
2600b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org}
2610b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2620b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2630b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.orgvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
2640b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                                           Register receiver,
2650b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                                           Register scratch,
2660b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                                           Label* miss_label) {
2670b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Check that the receiver isn't a smi.
2684af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  __ JumpIfSmi(receiver, miss_label);
2690b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2700b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Check that the object is a JS array.
2710b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
2720b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ j(not_equal, miss_label);
2730b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2740b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Load length directly from the JS array.
2750b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ movq(rax, FieldOperand(receiver, JSArray::kLengthOffset));
2760b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ ret(0);
2770b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org}
2780b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2790b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2800b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org// Generate code to check if an object is a string.  If the object is
2810b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org// a string, the map's instance type is left in the scratch register.
2820b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.orgstatic void GenerateStringCheck(MacroAssembler* masm,
2830b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                                Register receiver,
2840b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                                Register scratch,
2850b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                                Label* smi,
2860b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                                Label* non_string_object) {
2870b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Check that the object isn't a smi.
2884af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  __ JumpIfSmi(receiver, smi);
2890b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2900b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Check that the object is a string.
2910b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ movq(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
2920b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ movzxbq(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
29380c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kNotStringTag != 0);
2940b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ testl(scratch, Immediate(kNotStringTag));
2950b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ j(not_zero, non_string_object);
2960b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org}
2970b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2980b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2990b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.orgvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
3000b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                                            Register receiver,
3015c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                            Register scratch1,
3025c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                            Register scratch2,
303528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                            Label* miss) {
3045c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Label check_wrapper;
3050b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
3060b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Check if the object is a string leaving the instance type in the
3070b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // scratch register.
308528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper);
3090b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
3100b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Load length directly from the string.
311ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  __ movq(rax, FieldOperand(receiver, String::kLengthOffset));
3120b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ ret(0);
3130b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
314528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Check if the object is a JSValue wrapper.
315528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ bind(&check_wrapper);
316528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ cmpl(scratch1, Immediate(JS_VALUE_TYPE));
317528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ j(not_equal, miss);
318e76560e31adc252866988b6fed3bba91a0e2855chpayer@chromium.org
319528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Check if the wrapped value is a string and load the length
320528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // directly if it is.
321528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
322528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
323528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ movq(rax, FieldOperand(scratch2, String::kLengthOffset));
324528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ ret(0);
3250b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org}
3260b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
3270b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
3285d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.orgvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
3295d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                                                 Register receiver,
3305d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                                                 Register result,
3315d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                                                 Register scratch,
3325d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                                                 Label* miss_label) {
3335d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ TryGetFunctionPrototype(receiver, result, miss_label);
3345d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  if (!result.is(rax)) __ movq(rax, result);
3355d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ ret(0);
3365d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org}
3375d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
3385d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
33957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.orgvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
34057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            Register dst,
34157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            Register src,
34257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            bool inobject,
34357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            int index,
34457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            Representation representation) {
34557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  ASSERT(!FLAG_track_double_fields || !representation.IsDouble());
3464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  int offset = index * kPointerSize;
3474a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  if (!inobject) {
3484a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // Calculate the offset into the properties array.
3494a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    offset = offset + FixedArray::kHeaderSize;
3504a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset));
3514a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    src = dst;
3525d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
3534a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ movq(dst, FieldOperand(src, offset));
3545d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org}
3555d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
3565d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
3575d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.orgstatic void PushInterceptorArguments(MacroAssembler* masm,
3585d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                                     Register receiver,
3595d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                                     Register holder,
3605d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                                     Register name,
361c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                     Handle<JSObject> holder_obj) {
3624a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0);
3634a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1);
3644a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2);
3654a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3);
3664a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4);
3675d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ push(name);
368c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
369c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor));
370c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ Move(kScratchRegister, interceptor);
3715d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ push(kScratchRegister);
3725d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ push(receiver);
3735d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ push(holder);
3745d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org}
3755d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
3765d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
377c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgstatic void CompileCallLoadPropertyWithInterceptor(
378c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    MacroAssembler* masm,
379c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Register receiver,
380c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Register holder,
381c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Register name,
38237be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org    Handle<JSObject> holder_obj,
38337be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org    IC::UtilityId id) {
3840b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
38537be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org  __ CallExternalReference(
38637be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      ExternalReference(IC_Utility(id), masm->isolate()),
38737be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      StubCache::kInterceptorArgsLength);
3880b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org}
3890b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
3900b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
3914a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com// Number of pointers to be reserved on stack for fast API call.
392bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.orgstatic const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
3930b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
3945d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
3954a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com// Reserves space for the extra arguments to API function in the
3964111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org// caller's frame.
3974111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org//
3984111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org// These arguments are set by CheckPrototypes and GenerateFastApiCall.
3994111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.orgstatic void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
4004111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  // ----------- S t a t e -------------
4014111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  //  -- rsp[0] : return address
4024111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  //  -- rsp[8] : last argument in the internal frame of the caller
4034111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  // -----------------------------------
404d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org  __ movq(scratch, StackOperandForReturnAddress(0));
4054a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
406d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org  __ movq(StackOperandForReturnAddress(0), scratch);
407ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  __ Move(scratch, Smi::FromInt(0));
408662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  StackArgumentsAccessor args(rsp, kFastApiCallArguments,
409662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org                              ARGUMENTS_DONT_CONTAIN_RECEIVER);
410662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  for (int i = 0; i < kFastApiCallArguments; i++) {
411662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org     __ movq(args.GetArgumentOperand(i), scratch);
4124a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  }
4134111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org}
4144111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
4154111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
4164111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org// Undoes the effects of ReserveSpaceForFastApiCall.
4174111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.orgstatic void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
4184111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  // ----------- S t a t e -------------
419c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  //  -- rsp[0]                             : return address.
420c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  //  -- rsp[8]                             : last fast api call extra argument.
4214111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  //  -- ...
422c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  //  -- rsp[kFastApiCallArguments * 8]     : first fast api call extra
423c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  //                                          argument.
4244a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  //  -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal
4254a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  //                                          frame.
4264111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  // -----------------------------------
427d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org  __ movq(scratch, StackOperandForReturnAddress(0));
428d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org  __ movq(StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize),
429d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org          scratch);
4304a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments));
4314111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org}
4324111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
4334111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
4347ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.orgstatic void GenerateFastApiCallBody(MacroAssembler* masm,
4357ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                    const CallOptimization& optimization,
4367ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                    int argc,
4377ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                    bool restore_context);
4387ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
4397ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
4404a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com// Generates call to API function.
441c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgstatic void GenerateFastApiCall(MacroAssembler* masm,
442c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                const CallOptimization& optimization,
4437ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                int argc) {
444cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org  typedef FunctionCallbackArguments FCA;
445cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org  StackArgumentsAccessor args(rsp, argc + kFastApiCallArguments);
446528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
447528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Save calling context.
448fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  int offset = argc + kFastApiCallArguments;
449fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ movq(args.GetArgumentOperand(offset - FCA::kContextSaveIndex), rsi);
450528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
4514111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  // Get the function and setup the context.
452c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Handle<JSFunction> function = optimization.constant_function();
453c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ Move(rdi, function);
4544111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
455cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org  // Construct the FunctionCallbackInfo on the stack.
456fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ movq(args.GetArgumentOperand(offset - FCA::kCalleeIndex), rdi);
457c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
45809d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org  Handle<Object> call_data(api_call_info->data(), masm->isolate());
459c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (masm->isolate()->heap()->InNewSpace(*call_data)) {
460c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    __ Move(rcx, api_call_info);
4614111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
462fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org    __ movq(args.GetArgumentOperand(offset - FCA::kDataIndex), rbx);
4634111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  } else {
464fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org    __ Move(args.GetArgumentOperand(offset - FCA::kDataIndex), call_data);
4654111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  }
466e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  __ Move(kScratchRegister,
46732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org          ExternalReference::isolate_address(masm->isolate()));
468fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ movq(args.GetArgumentOperand(offset - FCA::kIsolateIndex),
469cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org          kScratchRegister);
470528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
471fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ movq(args.GetArgumentOperand(offset - FCA::kReturnValueDefaultValueIndex),
472fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org          kScratchRegister);
473fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ movq(args.GetArgumentOperand(offset - FCA::kReturnValueOffset),
474cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org          kScratchRegister);
4754111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
4764a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // Prepare arguments.
477528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  STATIC_ASSERT(kFastApiCallArguments == 7);
4787ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ lea(rax, Operand(rsp, 1 * kPointerSize));
4797ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
4807ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  GenerateFastApiCallBody(masm, optimization, argc, false);
4817ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org}
4827ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
4837ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
4847ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org// Generate call to api function.
4857ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org// This function uses push() to generate smaller, faster code than
4867ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org// the version above. It is an optimization that should will be removed
4877ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org// when api call ICs are generated in hydrogen.
4887ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.orgstatic void GenerateFastApiCall(MacroAssembler* masm,
4897ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                const CallOptimization& optimization,
4907ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                Register receiver,
4917ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                Register scratch1,
4927ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                Register scratch2,
4937ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                Register scratch3,
4947ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                int argc,
4957ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                Register* values) {
4967ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  ASSERT(optimization.is_simple_api_call());
4977ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
4987ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // Copy return value.
4997ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ pop(scratch1);
5007ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
5017ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // receiver
5027ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ push(receiver);
5037ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
5047ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // Write the arguments to stack frame.
5057ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  for (int i = 0; i < argc; i++) {
5067ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    Register arg = values[argc-1-i];
5077ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    ASSERT(!receiver.is(arg));
5087ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    ASSERT(!scratch1.is(arg));
5097ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    ASSERT(!scratch2.is(arg));
5107ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    ASSERT(!scratch3.is(arg));
5117ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    __ push(arg);
5127ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  }
5137ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
5147ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  typedef FunctionCallbackArguments FCA;
5157ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
5167ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  STATIC_ASSERT(FCA::kHolderIndex == 0);
5177ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  STATIC_ASSERT(FCA::kIsolateIndex == 1);
5187ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
5197ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  STATIC_ASSERT(FCA::kReturnValueOffset == 3);
5207ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  STATIC_ASSERT(FCA::kDataIndex == 4);
5217ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  STATIC_ASSERT(FCA::kCalleeIndex == 5);
5227ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  STATIC_ASSERT(FCA::kContextSaveIndex == 6);
5237ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  STATIC_ASSERT(FCA::kArgsLength == 7);
5247ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
5257ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // context save
5267ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ push(rsi);
5277ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
5287ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // Get the function and setup the context.
5297ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  Handle<JSFunction> function = optimization.constant_function();
5307ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ Move(scratch2, function);
5317ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ push(scratch2);
5327ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
5337ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  Isolate* isolate = masm->isolate();
5347ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
5357ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  Handle<Object> call_data(api_call_info->data(), isolate);
5367ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // Push data from ExecutableAccessorInfo.
5377ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  bool call_data_undefined = false;
5387ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  if (isolate->heap()->InNewSpace(*call_data)) {
5397ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    __ Move(scratch2, api_call_info);
5407ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    __ movq(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset));
5417ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  } else if (call_data->IsUndefined()) {
5427ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    call_data_undefined = true;
5437ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
5447ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  } else {
5457ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    __ Move(scratch3, call_data);
5467ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  }
5477ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // call data
5487ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ push(scratch3);
5497ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  if (!call_data_undefined) {
5507ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
5517ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  }
5527ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // return value
5537ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ push(scratch3);
5547ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // return value default
5557ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ push(scratch3);
5567ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // isolate
5577ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ Move(scratch3,
5587ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org          ExternalReference::isolate_address(masm->isolate()));
5597ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ push(scratch3);
5607ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // holder
5617ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ push(receiver);
5627ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
5637ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  ASSERT(!scratch1.is(rax));
5647ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // store receiver address for GenerateFastApiCallBody
5657ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ movq(rax, rsp);
566bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org
5677ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // return address
5687ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ push(scratch1);
5697ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
5707ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  GenerateFastApiCallBody(masm, optimization, argc, true);
5717ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org}
5727ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
5737ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
5747ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.orgstatic void GenerateFastApiCallBody(MacroAssembler* masm,
5757ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                    const CallOptimization& optimization,
5767ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                    int argc,
5777ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                                    bool restore_context) {
5787ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // ----------- S t a t e -------------
5797ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  //  -- rsp[0]              : return address
5807ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  //  -- rsp[8] - rsp[56]    : FunctionCallbackInfo, incl.
5817ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  //                         :  object passing the type check
5827ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  //                            (set by CheckPrototypes)
5837ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  //  -- rsp[64]             : last argument
5847ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  //  -- ...
5857ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  //  -- rsp[(argc + 7) * 8] : first argument
5867ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  //  -- rsp[(argc + 8) * 8] : receiver
5877ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  //
5887ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // rax : receiver address
5897ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  // -----------------------------------
5907ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  typedef FunctionCallbackArguments FCA;
5917ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org
5927ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
593bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  // Function address is a foreign pointer outside V8's heap.
594bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  Address function_address = v8::ToCData<Address>(api_call_info->callback());
5954111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
5964a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // Allocate the v8::Arguments structure in the arguments' space since
5974a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // it's not controlled by GC.
5984a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  const int kApiStackSpace = 4;
5994a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
600662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ PrepareCallApiFunction(kApiStackSpace);
6014a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
6027ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ movq(StackSpaceOperand(0), rax);  // FunctionCallbackInfo::implicit_args_.
6037ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ addq(rax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize));
6047ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ movq(StackSpaceOperand(1), rax);  // FunctionCallbackInfo::values_.
605fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ Set(StackSpaceOperand(2), argc);  // FunctionCallbackInfo::length_.
606fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  // FunctionCallbackInfo::is_construct_call_.
6074a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  __ Set(StackSpaceOperand(3), 0);
6084a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
609528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org#if defined(__MINGW64__) || defined(_WIN64)
610528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Register arguments_arg = rcx;
611528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Register callback_arg = rdx;
612528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org#else
613528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Register arguments_arg = rdi;
614528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Register callback_arg = rsi;
615528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org#endif
616528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
6174a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // v8::InvocationCallback's argument.
6184a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  __ lea(arguments_arg, StackSpaceOperand(0));
619c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
620662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
621b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
622d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  StackArgumentsAccessor args_from_rbp(rbp, kFastApiCallArguments,
623d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org                                       ARGUMENTS_DONT_CONTAIN_RECEIVER);
624d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  Operand context_restore_operand = args_from_rbp.GetArgumentOperand(
625d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org      kFastApiCallArguments - 1 - FCA::kContextSaveIndex);
626d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  Operand return_value_operand = args_from_rbp.GetArgumentOperand(
627d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org      kFastApiCallArguments - 1 - FCA::kReturnValueOffset);
628cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org  __ CallApiFunctionAndReturn(
629cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org      function_address,
630cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org      thunk_address,
631cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org      callback_arg,
632cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org      argc + kFastApiCallArguments + 1,
633cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org      return_value_operand,
634cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org      restore_context ? &context_restore_operand : NULL);
6354111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org}
6364111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
6374111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
6380b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.orgclass CallInterceptorCompiler BASE_EMBEDDED {
6390b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org public:
6408a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  CallInterceptorCompiler(CallStubCompiler* stub_compiler,
6414111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org                          const ParameterCount& arguments,
642d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                          Register name,
643cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org                          ExtraICState extra_ic_state)
6444111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org      : stub_compiler_(stub_compiler),
6454111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org        arguments_(arguments),
646d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org        name_(name),
647d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org        extra_ic_state_(extra_ic_state) {}
6484111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
649c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  void Compile(MacroAssembler* masm,
650c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Handle<JSObject> object,
651c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Handle<JSObject> holder,
652750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org               Handle<Name> name,
653c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               LookupResult* lookup,
654c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Register receiver,
655c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Register scratch1,
656c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Register scratch2,
657c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Register scratch3,
658c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Label* miss) {
6594111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    ASSERT(holder->HasNamedInterceptor());
6604111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
6614111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
6624111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    // Check that the receiver isn't a smi.
6634111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    __ JumpIfSmi(receiver, miss);
6644111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
6654111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    CallOptimization optimization(lookup);
6664111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    if (optimization.is_constant_call()) {
667c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
668c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                       holder, lookup, name, optimization, miss);
6694111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    } else {
670c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
671c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                     name, holder, miss);
6724111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    }
6734111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  }
6740b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
6754111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org private:
676c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  void CompileCacheable(MacroAssembler* masm,
677c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Handle<JSObject> object,
678c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Register receiver,
679c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Register scratch1,
680c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Register scratch2,
681c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Register scratch3,
682c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Handle<JSObject> interceptor_holder,
683c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        LookupResult* lookup,
684750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                        Handle<Name> name,
685c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        const CallOptimization& optimization,
686c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Label* miss_label) {
6874111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    ASSERT(optimization.is_constant_call());
6884111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    ASSERT(!lookup->holder()->IsGlobalObject());
6894111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
6904111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    int depth1 = kInvalidProtoDepth;
6914111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    int depth2 = kInvalidProtoDepth;
6924111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    bool can_do_fast_api_call = false;
6934111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    if (optimization.is_simple_api_call() &&
6944111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org        !lookup->holder()->IsGlobalObject()) {
695c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      depth1 = optimization.GetPrototypeDepthOfExpectedType(
696c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          object, interceptor_holder);
6974111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org      if (depth1 == kInvalidProtoDepth) {
698c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        depth2 = optimization.GetPrototypeDepthOfExpectedType(
699c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org            interceptor_holder, Handle<JSObject>(lookup->holder()));
7000b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org      }
701c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      can_do_fast_api_call =
702c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
7030b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org    }
7040b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
7057979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    Counters* counters = masm->isolate()->counters();
7067979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    __ IncrementCounter(counters->call_const_interceptor(), 1);
7074111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
7084111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    if (can_do_fast_api_call) {
7097979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org      __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
7104111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org      ReserveSpaceForFastApiCall(masm, scratch1);
7110b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org    }
7120b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
7139155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org    // Check that the maps from receiver to interceptor's holder
7149155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org    // haven't changed and thus we can invoke interceptor.
7154111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    Label miss_cleanup;
7164111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
7174111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    Register holder =
718f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        stub_compiler_->CheckPrototypes(
719f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            IC::CurrentTypeOf(object, masm->isolate()), receiver,
720f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            interceptor_holder, scratch1, scratch2, scratch3,
721f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            name, depth1, miss);
7225c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7239155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org    // Invoke an interceptor and if it provides a value,
7249155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org    // branch to |regular_invoke|.
7254111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    Label regular_invoke;
7269155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org    LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
7279155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org                        &regular_invoke);
7280b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
7299155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org    // Interceptor returned nothing for this property.  Try to use cached
7309155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org    // constant function.
7310b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
7329155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org    // Check that the maps from interceptor's holder to constant function's
7339155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org    // holder haven't changed and thus we can use cached constant function.
734c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    if (*interceptor_holder != lookup->holder()) {
735f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      stub_compiler_->CheckPrototypes(
7362c45addeb1788c63746dd1ba81bf801951ac8e3bverwaest@chromium.org          IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
737f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org          handle(lookup->holder()), scratch1, scratch2, scratch3,
738f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org          name, depth2, miss);
73930ce411529579186181838984710b0b0980857aaricow@chromium.org    } else {
74030ce411529579186181838984710b0b0980857aaricow@chromium.org      // CheckPrototypes has a side effect of fetching a 'holder'
74130ce411529579186181838984710b0b0980857aaricow@chromium.org      // for API (object which is instanceof for the signature).  It's
74230ce411529579186181838984710b0b0980857aaricow@chromium.org      // safe to omit it here, as if present, it should be fetched
74330ce411529579186181838984710b0b0980857aaricow@chromium.org      // by the previous CheckPrototypes.
74430ce411529579186181838984710b0b0980857aaricow@chromium.org      ASSERT(depth2 == kInvalidProtoDepth);
74530ce411529579186181838984710b0b0980857aaricow@chromium.org    }
7460b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
7479155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org    // Invoke function.
7484111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    if (can_do_fast_api_call) {
7497ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org      GenerateFastApiCall(masm, optimization, arguments_.immediate());
7504111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    } else {
75132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      Handle<JSFunction> fun = optimization.constant_function();
7522c45addeb1788c63746dd1ba81bf801951ac8e3bverwaest@chromium.org      stub_compiler_->GenerateJumpFunction(object, fun);
7534111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    }
7540b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
7559155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org    // Deferred code for fast API call case---clean preallocated space.
7564111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    if (can_do_fast_api_call) {
7574111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org      __ bind(&miss_cleanup);
7584111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org      FreeSpaceForFastApiCall(masm, scratch1);
7594111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org      __ jmp(miss_label);
7604111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    }
7610b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
7629155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org    // Invoke a regular function.
7634111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    __ bind(&regular_invoke);
7644111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    if (can_do_fast_api_call) {
7654111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org      FreeSpaceForFastApiCall(masm, scratch1);
7664111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    }
7670b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  }
7680b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
7690b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  void CompileRegular(MacroAssembler* masm,
770c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                      Handle<JSObject> object,
7710b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                      Register receiver,
7724111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org                      Register scratch1,
7734111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org                      Register scratch2,
7746a2b0aa331a1ae1829a9b9637ad18cfc7ec9d840ager@chromium.org                      Register scratch3,
775750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                      Handle<Name> name,
776c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                      Handle<JSObject> interceptor_holder,
7770b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                      Label* miss_label) {
7784111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    Register holder =
779f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        stub_compiler_->CheckPrototypes(
780f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            IC::CurrentTypeOf(object, masm->isolate()), receiver,
781f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            interceptor_holder, scratch1, scratch2, scratch3, name, miss_label);
7824111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
783c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::INTERNAL);
7845c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // Save the name_ register across the call.
7855c838251403b0be9a882540f1922577abba4c872ager@chromium.org    __ push(name_);
7860b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
78737be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org    CompileCallLoadPropertyWithInterceptor(
78837be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org        masm, receiver, holder, name_, interceptor_holder,
78937be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org        IC::kLoadPropertyWithInterceptorForCall);
7900b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
7914111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    // Restore the name_ register.
7925c838251403b0be9a882540f1922577abba4c872ager@chromium.org    __ pop(name_);
793c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
794c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Leave the internal frame.
7950b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  }
7960b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
7974111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  void LoadWithInterceptor(MacroAssembler* masm,
7984111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org                           Register receiver,
7994111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org                           Register holder,
800c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                           Handle<JSObject> holder_obj,
8014111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org                           Label* interceptor_succeeded) {
802c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
803c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FrameScope scope(masm, StackFrame::INTERNAL);
8042c45addeb1788c63746dd1ba81bf801951ac8e3bverwaest@chromium.org      __ push(receiver);
8052c45addeb1788c63746dd1ba81bf801951ac8e3bverwaest@chromium.org      __ push(holder);
8062c45addeb1788c63746dd1ba81bf801951ac8e3bverwaest@chromium.org      __ push(name_);
807c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
80837be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      CompileCallLoadPropertyWithInterceptor(
80937be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org          masm, receiver, holder, name_, holder_obj,
81037be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org          IC::kLoadPropertyWithInterceptorOnly);
811c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
8122c45addeb1788c63746dd1ba81bf801951ac8e3bverwaest@chromium.org      __ pop(name_);
8132c45addeb1788c63746dd1ba81bf801951ac8e3bverwaest@chromium.org      __ pop(holder);
8142c45addeb1788c63746dd1ba81bf801951ac8e3bverwaest@chromium.org      __ pop(receiver);
815c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Leave the internal frame.
816c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
8174111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
8184111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
8194111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    __ j(not_equal, interceptor_succeeded);
8204111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org  }
8214111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org
8228a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  CallStubCompiler* stub_compiler_;
8230b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  const ParameterCount& arguments_;
8245c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Register name_;
825cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  ExtraICState extra_ic_state_;
8260b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org};
8270b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
8280b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
8292efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
8302efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                            Label* label,
8312efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                            Handle<Name> name) {
8322bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  if (!label->is_unused()) {
8332bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    __ bind(label);
8342bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    __ Move(this->name(), name);
8352bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  }
836ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org}
837ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org
838ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org
839057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.orgvoid StubCompiler::GenerateCheckPropertyCell(MacroAssembler* masm,
840057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                             Handle<JSGlobalObject> global,
841057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                             Handle<Name> name,
842057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                             Register scratch,
843057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                             Label* miss) {
844b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  Handle<PropertyCell> cell =
845057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org      JSGlobalObject::EnsurePropertyCell(global, name);
846e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(cell->value()->IsTheHole());
847e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ Move(scratch, cell);
84841728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  __ Cmp(FieldOperand(scratch, Cell::kValueOffset),
849e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org         masm->isolate()->factory()->the_hole_value());
850e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ j(not_equal, miss);
851e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
852e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
853e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
8542efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid StoreStubCompiler::GenerateNegativeHolderLookup(
855bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    MacroAssembler* masm,
856bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Handle<JSObject> holder,
857bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Register holder_reg,
858bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Handle<Name> name,
859bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Label* miss) {
860bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  if (holder->IsJSGlobalObject()) {
861bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    GenerateCheckPropertyCell(
862057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org        masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss);
863bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) {
864bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    GenerateDictionaryNegativeLookup(
865bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        masm, miss, holder_reg, name, scratch1(), scratch2());
8667028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  }
867bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org}
8687028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
869bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
870bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
871bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// store is successful.
8722efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
8732efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Handle<JSObject> object,
8742efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                LookupResult* lookup,
8752efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Handle<Map> transition,
8762efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Handle<Name> name,
8772efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register receiver_reg,
8782efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register storage_reg,
8792efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register value_reg,
8802efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register scratch1,
8812efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register scratch2,
8822efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register unused,
8832efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Label* miss_label,
8842efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Label* slow) {
885f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  int descriptor = transition->LastAdded();
886f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  DescriptorArray* descriptors = transition->instance_descriptors();
887f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  PropertyDetails details = descriptors->GetDetails(descriptor);
888f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  Representation representation = details.representation();
889f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  ASSERT(!representation.IsNone());
890f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
891fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  if (details.type() == CONSTANT) {
892fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org    Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate());
893c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    __ Cmp(value_reg, constant);
894bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ j(not_equal, miss_label);
895b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  } else if (FLAG_track_fields && representation.IsSmi()) {
896bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ JumpIfNotSmi(value_reg, miss_label);
897906e2fb760f52fe6e75b744b1ea42576ea5b2c29ulan@chromium.org  } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
898bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ JumpIfSmi(value_reg, miss_label);
89957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  } else if (FLAG_track_double_fields && representation.IsDouble()) {
90057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    Label do_store, heap_number;
90157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ AllocateHeapNumber(storage_reg, scratch1, slow);
90257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
90357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ JumpIfNotSmi(value_reg, &heap_number);
90457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ SmiToInteger32(scratch1, value_reg);
905528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    __ Cvtlsi2sd(xmm0, scratch1);
90657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ jmp(&do_store);
90757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
90857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ bind(&heap_number);
90957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(),
910bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                miss_label, DONT_DO_SMI_CHECK);
91157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
91257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
91357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ bind(&do_store);
91457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0);
91557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  }
91657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
9175d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Stub never generated for non-global objects that require access
9185d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // checks.
9195d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
9205d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
9215d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Perform map transition for the receiver if necessary.
922b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  if (details.type() == FIELD &&
923b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org      object->map()->unused_property_fields() == 0) {
9245d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // The properties must be extended before we can store the value.
9255d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // We jump to a runtime call that extends the properties array.
926594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ PopReturnAddressTo(scratch1);
9275d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    __ push(receiver_reg);
928394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ Push(transition);
9292bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    __ push(value_reg);
930594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ PushReturnAddressFrom(scratch1);
9315d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    __ TailCallExternalReference(
932ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
933ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                          masm->isolate()),
934ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org        3,
935ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org        1);
9365d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    return;
9375d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
9385d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
939e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Update the map of the object.
940e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ Move(scratch1, transition);
941e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ movq(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1);
942e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
94357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  // Update the write barrier for the map field.
944e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ RecordWriteField(receiver_reg,
945e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      HeapObject::kMapOffset,
946e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      scratch1,
94757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      scratch2,
948e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      kDontSaveFPRegs,
949e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      OMIT_REMEMBERED_SET,
950e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      OMIT_SMI_CHECK);
951e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
952fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  if (details.type() == CONSTANT) {
953b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    ASSERT(value_reg.is(rax));
954b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    __ ret(0);
955b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    return;
956b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  }
957b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
958e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  int index = transition->instance_descriptors()->GetFieldIndex(
959e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      transition->LastAdded());
9605d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
9615d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Adjust for the number of properties stored in the object. Even in the
9625d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // face of a transition we can use the old map here because the size of the
9635d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // object and the number of in-object properties is not going to change.
9645d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  index -= object->map()->inobject_properties();
9655d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
966e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // TODO(verwaest): Share this code as a code stub.
967a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  SmiCheck smi_check = representation.IsTagged()
968a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
9695d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  if (index < 0) {
9705d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // Set the property straight into the object.
9715d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    int offset = object->map()->instance_size() + (index * kPointerSize);
97257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    if (FLAG_track_double_fields && representation.IsDouble()) {
97357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ movq(FieldOperand(receiver_reg, offset), storage_reg);
97457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    } else {
97557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ movq(FieldOperand(receiver_reg, offset), value_reg);
97657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    }
9775d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
978f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    if (!FLAG_track_fields || !representation.IsSmi()) {
979f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Update the write barrier for the array address.
98057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      if (!FLAG_track_double_fields || !representation.IsDouble()) {
981bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        __ movq(storage_reg, value_reg);
98257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      }
983f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ RecordWriteField(
984bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org          receiver_reg, offset, storage_reg, scratch1, kDontSaveFPRegs,
985a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org          EMIT_REMEMBERED_SET, smi_check);
986f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
9875d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  } else {
9885d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // Write to the properties array.
9895d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    int offset = index * kPointerSize + FixedArray::kHeaderSize;
9905d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // Get the properties array (optimistically).
9917028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
99257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    if (FLAG_track_double_fields && representation.IsDouble()) {
99357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ movq(FieldOperand(scratch1, offset), storage_reg);
99457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    } else {
99557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ movq(FieldOperand(scratch1, offset), value_reg);
99657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    }
9975d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
998f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    if (!FLAG_track_fields || !representation.IsSmi()) {
999f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Update the write barrier for the array address.
100057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      if (!FLAG_track_double_fields || !representation.IsDouble()) {
1001bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        __ movq(storage_reg, value_reg);
100257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      }
1003f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ RecordWriteField(
1004bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org          scratch1, offset, storage_reg, receiver_reg, kDontSaveFPRegs,
1005a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org          EMIT_REMEMBERED_SET, smi_check);
1006f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
10075d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
10085d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
10095d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Return the value (register rax).
10102bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  ASSERT(value_reg.is(rax));
10115d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ ret(0);
10125d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org}
10135d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
10145d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
1015e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// Both name_reg and receiver_reg are preserved on jumps to miss_label,
1016e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// but may be destroyed if store is successful.
10172efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
10182efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Handle<JSObject> object,
10192efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           LookupResult* lookup,
10202efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register receiver_reg,
10212efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register name_reg,
10222efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register value_reg,
10232efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register scratch1,
10242efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register scratch2,
10252efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Label* miss_label) {
1026e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Stub never generated for non-global objects that require access
1027e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // checks.
1028e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
1029e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
1030e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  int index = lookup->GetFieldIndex().field_index();
1031e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
1032e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Adjust for the number of properties stored in the object. Even in the
1033e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // face of a transition we can use the old map here because the size of the
1034e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // object and the number of in-object properties is not going to change.
1035e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  index -= object->map()->inobject_properties();
1036e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
1037f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  Representation representation = lookup->representation();
1038f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  ASSERT(!representation.IsNone());
1039f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  if (FLAG_track_fields && representation.IsSmi()) {
1040f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    __ JumpIfNotSmi(value_reg, miss_label);
1041906e2fb760f52fe6e75b744b1ea42576ea5b2c29ulan@chromium.org  } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
1042906e2fb760f52fe6e75b744b1ea42576ea5b2c29ulan@chromium.org    __ JumpIfSmi(value_reg, miss_label);
1043f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  } else if (FLAG_track_double_fields && representation.IsDouble()) {
104457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    // Load the double storage.
104557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    if (index < 0) {
104657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      int offset = object->map()->instance_size() + (index * kPointerSize);
104757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ movq(scratch1, FieldOperand(receiver_reg, offset));
104857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    } else {
104957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ movq(scratch1,
105057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org              FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
105157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      int offset = index * kPointerSize + FixedArray::kHeaderSize;
105257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ movq(scratch1, FieldOperand(scratch1, offset));
105357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    }
105457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
105557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    // Store the value into the storage.
105657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    Label do_store, heap_number;
105757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ JumpIfNotSmi(value_reg, &heap_number);
105857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ SmiToInteger32(scratch2, value_reg);
1059528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    __ Cvtlsi2sd(xmm0, scratch2);
106057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ jmp(&do_store);
106157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
106257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ bind(&heap_number);
1063f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(),
1064a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                miss_label, DONT_DO_SMI_CHECK);
106557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
1066f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    __ bind(&do_store);
106757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0);
106857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    // Return the value (register rax).
106957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    ASSERT(value_reg.is(rax));
107057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ ret(0);
107157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    return;
1072f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  }
1073f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
1074e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // TODO(verwaest): Share this code as a code stub.
1075a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  SmiCheck smi_check = representation.IsTagged()
1076a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
1077e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (index < 0) {
1078e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Set the property straight into the object.
1079e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    int offset = object->map()->instance_size() + (index * kPointerSize);
1080e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ movq(FieldOperand(receiver_reg, offset), value_reg);
1081e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
1082f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    if (!FLAG_track_fields || !representation.IsSmi()) {
1083f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Update the write barrier for the array address.
1084f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Pass the value being stored in the now unused name_reg.
1085f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ movq(name_reg, value_reg);
1086f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ RecordWriteField(
1087a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org          receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs,
1088a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org          EMIT_REMEMBERED_SET, smi_check);
1089f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
1090e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  } else {
1091e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Write to the properties array.
1092e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    int offset = index * kPointerSize + FixedArray::kHeaderSize;
1093e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Get the properties array (optimistically).
1094e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
1095e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ movq(FieldOperand(scratch1, offset), value_reg);
1096e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
1097f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    if (!FLAG_track_fields || !representation.IsSmi()) {
1098f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Update the write barrier for the array address.
1099f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Pass the value being stored in the now unused name_reg.
1100f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ movq(name_reg, value_reg);
1101f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ RecordWriteField(
1102a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org          scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs,
1103a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org          EMIT_REMEMBERED_SET, smi_check);
1104f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
1105e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
1106e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
1107e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Return the value (register rax).
1108e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(value_reg.is(rax));
1109e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ ret(0);
1110394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
1111394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1112394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
11132bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.orgvoid StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
11144a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ jmp(code, RelocInfo::CODE_TARGET);
11154a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
11164a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
11174a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
11182bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org#undef __
11192bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org#define __ ACCESS_MASM((masm()))
11202bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
11212bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
1122f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgRegister StubCompiler::CheckPrototypes(Handle<Type> type,
1123394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Register object_reg,
1124394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Handle<JSObject> holder,
1125394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Register holder_reg,
1126394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Register scratch1,
1127394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Register scratch2,
1128750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                       Handle<Name> name,
1129394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       int save_at_depth,
11304a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                                       Label* miss,
11314a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                                       PrototypeCheckType check) {
1132f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
1133ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Make sure that the type feedback oracle harvests the receiver map.
1134ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // TODO(svenpanne) Remove this hack when all ICs are reworked.
1135f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  __ Move(scratch1, receiver_map);
1136ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
1137394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Make sure there's no overlap between holder and object registers.
1138394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
1139394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1140394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com         && !scratch2.is(scratch1));
1141394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1142394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Keep track of the current object in register reg.  On the first
1143394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // iteration, reg is an alias for object_reg, on later iterations,
1144394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // it is an alias for holder_reg.
1145394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Register reg = object_reg;
1146394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  int depth = 0;
1147394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1148d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  StackArgumentsAccessor args(rsp, kFastApiCallArguments,
1149d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org                              ARGUMENTS_DONT_CONTAIN_RECEIVER);
1150d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  const int kHolderIndex = kFastApiCallArguments - 1 -
1151d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org      FunctionCallbackArguments::kHolderIndex;
1152d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
1153394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  if (save_at_depth == depth) {
1154d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    __ movq(args.GetArgumentOperand(kHolderIndex), object_reg);
1155394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
1156394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1157f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<JSObject> current = Handle<JSObject>::null();
1158f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
1159f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<JSObject> prototype = Handle<JSObject>::null();
1160f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<Map> current_map = receiver_map;
1161f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<Map> holder_map(holder->map());
1162f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  // Traverse the prototype chain and check the maps in the prototype chain for
1163f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  // fast and global objects or do negative lookup for normal objects.
1164f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  while (!current_map.is_identical_to(holder_map)) {
1165394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    ++depth;
1166394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1167394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Only global objects and objects that do not require access
1168394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // checks are allowed in stubs.
1169f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    ASSERT(current_map->IsJSGlobalProxyMap() ||
1170f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org           !current_map->is_access_check_needed());
1171394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1172f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    prototype = handle(JSObject::cast(current_map->prototype()));
1173f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    if (current_map->is_dictionary_map() &&
1174f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        !current_map->IsJSGlobalObjectMap() &&
1175f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        !current_map->IsJSGlobalProxyMap()) {
1176750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      if (!name->IsUniqueName()) {
1177750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org        ASSERT(name->IsString());
1178750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org        name = factory()->InternalizeString(Handle<String>::cast(name));
1179394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      }
1180f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      ASSERT(current.is_null() ||
1181f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org             current->property_dictionary()->FindEntry(*name) ==
1182750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org             NameDictionary::kNotFound);
1183394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1184394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
1185394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       scratch1, scratch2);
1186394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1187394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
1188394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      reg = holder_reg;  // From now on the object will be in holder_reg.
1189394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
1190394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    } else {
1191394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      bool in_new_space = heap()->InNewSpace(*prototype);
1192394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      if (in_new_space) {
1193394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // Save the map in scratch1 for later.
1194394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
1195394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      }
1196f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      if (depth != 1 || check == CHECK_ALL_MAPS) {
1197a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org        __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
11984a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      }
1199f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com
1200394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      // Check access rights to the global object.  This has to happen after
1201394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      // the map check so that we know that the object is actually a global
1202394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      // object.
1203f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      if (current_map->IsJSGlobalProxyMap()) {
1204394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        __ CheckAccessGlobalProxy(reg, scratch2, miss);
1205f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      } else if (current_map->IsJSGlobalObjectMap()) {
1206f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        GenerateCheckPropertyCell(
1207f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            masm(), Handle<JSGlobalObject>::cast(current), name,
1208f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            scratch2, miss);
1209394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      }
1210394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      reg = holder_reg;  // From now on the object will be in holder_reg.
1211394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1212394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      if (in_new_space) {
1213394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // The prototype is in new space; we cannot store a reference to it
1214394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // in the code.  Load it from the map.
1215394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
1216394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      } else {
1217394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // The prototype is in old space; load it directly.
1218394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        __ Move(reg, prototype);
1219394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      }
1220394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    }
1221394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1222394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    if (save_at_depth == depth) {
1223d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org      __ movq(args.GetArgumentOperand(kHolderIndex), reg);
1224394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    }
1225394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1226394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Go to the next object in the prototype chain.
1227394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    current = prototype;
1228f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    current_map = handle(current->map());
1229394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
1230394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1231394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Log the check depth.
1232394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1233394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1234f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  if (depth != 0 || check == CHECK_ALL_MAPS) {
12354a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // Check the holder map.
1236f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
12374a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  }
1238394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1239394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Perform security check for access to the global object.
1240f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  ASSERT(current_map->IsJSGlobalProxyMap() ||
1241f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org         !current_map->is_access_check_needed());
1242f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  if (current_map->IsJSGlobalProxyMap()) {
1243394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ CheckAccessGlobalProxy(reg, scratch1, miss);
1244394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
1245394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1246394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Return the register containing the holder.
1247394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  return reg;
1248394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
1249394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1250394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1251b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.orgvoid LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
12524a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  if (!miss->is_unused()) {
1253b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    Label success;
1254b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    __ jmp(&success);
12554a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ bind(miss);
12562bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    TailCallBuiltin(masm(), MissBuiltin(kind()));
1257b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    __ bind(&success);
12584a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  }
12595aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
12605aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
12615aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
1262b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.orgvoid StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
1263bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  if (!miss->is_unused()) {
1264b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    Label success;
1265b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    __ jmp(&success);
1266bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    GenerateRestoreName(masm(), miss, name);
1267bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    TailCallBuiltin(masm(), MissBuiltin(kind()));
1268b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    __ bind(&success);
1269bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
1270bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org}
1271bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
1272bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
12732efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgRegister LoadStubCompiler::CallbackHandlerFrontend(
1274f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    Handle<Type> type,
12758432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Register object_reg,
12768432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Handle<JSObject> holder,
1277750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    Handle<Name> name,
12782c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org    Handle<Object> callback) {
12798432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  Label miss;
12808432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org
1281f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss);
12828432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org
12838432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
12848432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    ASSERT(!reg.is(scratch2()));
12858432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    ASSERT(!reg.is(scratch3()));
12868432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    ASSERT(!reg.is(scratch4()));
12878432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org
12888432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    // Load the properties dictionary.
12898432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Register dictionary = scratch4();
12908432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    __ movq(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset));
12918432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org
12928432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    // Probe the dictionary.
12938432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Label probe_done;
1294750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    NameDictionaryLookupStub::GeneratePositiveLookup(masm(),
1295750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                     &miss,
1296750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                     &probe_done,
1297750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                     dictionary,
1298750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                     this->name(),
1299750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                     scratch2(),
1300750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                     scratch3());
13018432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    __ bind(&probe_done);
13028432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org
13038432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    // If probing finds an entry in the dictionary, scratch3 contains the
13048432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    // index into the dictionary. Check that the value is the callback.
13058432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Register index = scratch3();
13068432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    const int kElementsStartOffset =
1307750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org        NameDictionary::kHeaderSize +
1308750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org        NameDictionary::kElementsStartIndex * kPointerSize;
13098432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    const int kValueOffset = kElementsStartOffset + kPointerSize;
13108432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    __ movq(scratch2(),
13118432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org            Operand(dictionary, index, times_pointer_size,
13128432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org                    kValueOffset - kHeapObjectTag));
13138432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    __ movq(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT);
13148432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    __ cmpq(scratch2(), scratch3());
13158432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    __ j(not_equal, &miss);
13168432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  }
13178432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org
1318b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  HandlerFrontendFooter(name, &miss);
13198432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  return reg;
132088767247437a4504f433cc5abea22a473e5ed982erik.corry@gmail.com}
132188767247437a4504f433cc5abea22a473e5ed982erik.corry@gmail.com
132288767247437a4504f433cc5abea22a473e5ed982erik.corry@gmail.com
13232efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadField(Register reg,
1324057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                         Handle<JSObject> holder,
1325057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                         PropertyIndex field,
1326057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                         Representation representation) {
132757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  if (!reg.is(receiver())) __ movq(receiver(), reg);
132857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  if (kind() == Code::LOAD_IC) {
132957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    LoadFieldStub stub(field.is_inobject(holder),
133057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                       field.translate(holder),
133157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                       representation);
133257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    GenerateTailCall(masm(), stub.GetCode(isolate()));
133357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  } else {
133457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    KeyedLoadFieldStub stub(field.is_inobject(holder),
133557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                            field.translate(holder),
133657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                            representation);
133757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    GenerateTailCall(masm(), stub.GetCode(isolate()));
133857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  }
13398432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org}
13408432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org
13418432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org
13422efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadCallback(
13432c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org    const CallOptimization& call_optimization) {
1344639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  GenerateFastApiCall(
13457ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org      masm(), call_optimization, receiver(),
13467ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org      scratch1(), scratch2(), name(), 0, NULL);
13472c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org}
13482c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org
13492c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org
13502efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadCallback(
13518432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Register reg,
13528432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Handle<ExecutableAccessorInfo> callback) {
13535d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Insert additional parameters into the stack frame above return address.
1354c9db920c61872265c3fdc00d745a9b1eebbfc0bedanno@chromium.org  ASSERT(!scratch4().is(reg));
1355594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ PopReturnAddressTo(scratch4());
13562c186ca6690a1cb19ec7584e71f167234587c87cwhesse@chromium.org
1357fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0);
1358fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1);
1359fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2);
1360fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3);
1361fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4);
1362fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5);
1363fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6);
13648432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  __ push(receiver());  // receiver
1365c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (heap()->InNewSpace(callback->data())) {
13664a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    ASSERT(!scratch2().is(reg));
13674a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ Move(scratch2(), callback);
13684a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ push(FieldOperand(scratch2(),
13698432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org                         ExecutableAccessorInfo::kDataOffset));  // data
13705d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  } else {
137109d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org    __ Push(Handle<Object>(callback->data(), isolate()));
13725d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
13734a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  ASSERT(!kScratchRegister.is(reg));
1374bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
1375bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ push(kScratchRegister);  // return value
13768a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ push(kScratchRegister);  // return value default
137753ad17558c81e6099cef4442237d7da643a5becfsvenpanne@chromium.org  __ PushAddress(ExternalReference::isolate_address(isolate()));
13784a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ push(reg);  // holder
13798432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  __ push(name());  // name
13804a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Save a pointer to where we pushed the arguments pointer.  This will be
1381fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  // passed as the const PropertyAccessorInfo& to the C++ callback.
1382ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1383bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  Address getter_address = v8::ToCData<Address>(callback->getter());
1384bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org
1385662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org#if defined(__MINGW64__) || defined(_WIN64)
1386b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  Register getter_arg = r8;
1387ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  Register accessor_info_arg = rdx;
1388ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  Register name_arg = rcx;
13895d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org#else
1390b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  Register getter_arg = rdx;
13915d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Register accessor_info_arg = rsi;
13925d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Register name_arg = rdi;
13935d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org#endif
1394ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1395c9db920c61872265c3fdc00d745a9b1eebbfc0bedanno@chromium.org  ASSERT(!name_arg.is(scratch4()));
13965d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ movq(name_arg, rsp);
1397594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ PushReturnAddressFrom(scratch4());
1398ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1399bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  // v8::Arguments::values_ and handler for name.
1400bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1;
1401ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
14025d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Allocate v8::AccessorInfo in non-GCed stack space.
14035d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  const int kArgStackSpace = 1;
1404ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1405662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ PrepareCallApiFunction(kArgStackSpace);
1406fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ lea(rax, Operand(name_arg, 1 * kPointerSize));
1407ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1408fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  // v8::PropertyAccessorInfo::args_.
14095d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ movq(StackSpaceOperand(0), rax);
1410ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
14115d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // The context register (rsi) has been saved in PrepareCallApiFunction and
14125d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // could be used to pass arguments.
14135d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ lea(accessor_info_arg, StackSpaceOperand(0));
1414ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1415662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
1416b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
1417d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  // The name handler is counted as an argument.
1418d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength);
1419d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  Operand return_value_operand = args.GetArgumentOperand(
1420d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org      PropertyCallbackArguments::kArgsLength - 1 -
1421d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org      PropertyCallbackArguments::kReturnValueOffset);
1422bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ CallApiFunctionAndReturn(getter_address,
1423b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org                              thunk_address,
1424b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org                              getter_arg,
1425bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org                              kStackSpace,
1426d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org                              return_value_operand,
1427528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                              NULL);
14285d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org}
1429ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1430ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
14312efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
14325d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Return the constant value.
1433c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ Move(rax, value);
14345d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ ret(0);
14355d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org}
1436ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1437ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
14382efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadInterceptor(
14398432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Register holder_reg,
1440b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    Handle<Object> object,
14418432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Handle<JSObject> interceptor_holder,
14428432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    LookupResult* lookup,
1443750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    Handle<Name> name) {
14445d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  ASSERT(interceptor_holder->HasNamedInterceptor());
14455d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1446ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
14475d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // So far the most popular follow ups for interceptor loads are FIELD
14485d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // and CALLBACKS, so inline only them, other cases may be added
14495d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // later.
14505d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  bool compile_followup_inline = false;
145105ed9ddc6ff3a1ab3983c50d378cddfa257869b6jkummerow@chromium.org  if (lookup->IsFound() && lookup->IsCacheable()) {
1452de0db002768654f346a9059d80ab47602018bfa0yangguo@chromium.org    if (lookup->IsField()) {
14535d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      compile_followup_inline = true;
14545d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    } else if (lookup->type() == CALLBACKS &&
14557c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org               lookup->GetCallbackObject()->IsExecutableAccessorInfo()) {
14567c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org      ExecutableAccessorInfo* callback =
14577c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org          ExecutableAccessorInfo::cast(lookup->GetCallbackObject());
14587028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      compile_followup_inline = callback->getter() != NULL &&
14597028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          callback->IsCompatibleReceiver(*object);
14605d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    }
14615d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
14625ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org
14635d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  if (compile_followup_inline) {
14645d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // Compile the interceptor call, followed by inline code to load the
14655d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // property from further up the prototype chain if the call fails.
14665d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // Check that the maps haven't changed.
14678432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
1468ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1469212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    // Preserve the receiver register explicitly whenever it is different from
1470212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    // the holder and it is needed should the interceptor return without any
1471212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    // result. The CALLBACKS case needs the receiver to be passed into C++ code,
1472212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    // the FIELD case might cause a miss during the prototype check.
1473212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
14748432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
1475212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org        (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
1476212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org
14775d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // Save necessary data before invoking an interceptor.
14785d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // Requires a frame to make GC aware of pushed pointers.
1479c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
1480c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FrameScope frame_scope(masm(), StackFrame::INTERNAL);
1481303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org
1482212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org      if (must_preserve_receiver_reg) {
14838432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org        __ push(receiver());
1484c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
1485c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ push(holder_reg);
14868432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org      __ push(this->name());
1487ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1488c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Invoke an interceptor.  Note: map checks from receiver to
1489c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // interceptor's holder has been compiled before (see a caller
1490c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // of this method.)
149137be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      CompileCallLoadPropertyWithInterceptor(
149237be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org          masm(), receiver(), holder_reg, this->name(), interceptor_holder,
149337be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org          IC::kLoadPropertyWithInterceptorOnly);
1494c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1495c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Check if interceptor provided a value for property.  If it's
1496c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // the case, return immediately.
1497c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Label interceptor_failed;
1498c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
1499c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ j(equal, &interceptor_failed);
1500c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      frame_scope.GenerateLeaveFrame();
1501c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ ret(0);
1502c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1503c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ bind(&interceptor_failed);
15048432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org      __ pop(this->name());
1505c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ pop(holder_reg);
1506212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org      if (must_preserve_receiver_reg) {
15078432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org        __ pop(receiver());
1508c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
1509ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1510c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Leave the internal frame.
1511c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
1512ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
15138432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup);
15145d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  } else {  // !compile_followup_inline
15155d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // Call the runtime system to load the interceptor.
15165d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // Check that the maps haven't changed.
1517594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ PopReturnAddressTo(scratch2());
15188432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    PushInterceptorArguments(masm(), receiver(), holder_reg,
15198432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org                             this->name(), interceptor_holder);
1520594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ PushReturnAddressFrom(scratch2());
1521ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
15225d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    ExternalReference ref = ExternalReference(
15237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org        IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate());
15244a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1);
1525303ada708275d2d425b846fb237f1ba7598ee239lrn@chromium.org  }
1526ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org}
1527ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1528ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1529750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgvoid CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
15305d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  if (kind_ == Code::KEYED_CALL_IC) {
1531394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ Cmp(rcx, name);
15325d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    __ j(not_equal, miss);
15335d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
15345d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org}
1535ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1536ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
15378a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.orgvoid CallStubCompiler::GenerateFunctionCheck(Register function,
15388a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                                             Register scratch,
15398a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                                             Label* miss) {
15408a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  __ JumpIfSmi(function, miss);
15418a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
15428a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  __ j(not_equal, miss);
15438a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org}
15448a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org
15458a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org
1546c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid CallStubCompiler::GenerateLoadFunctionFromCell(
154741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    Handle<Cell> cell,
1548c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
1549c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Label* miss) {
15505d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Get the value from the cell.
1551c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ Move(rdi, cell);
155241728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset));
155365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
15545d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Check that the cell contains the same function.
1555c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (heap()->InNewSpace(*function)) {
15565d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // We can't embed a pointer to a function in new space so we have
15575d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // to verify that the shared function info is unchanged. This has
15585d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // the nice side effect that multiple closures based on the same
15595d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // function can all use this call IC. Before we load through the
15605d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // function, we have to verify that it still is a function.
15618a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org    GenerateFunctionCheck(rdi, rax, miss);
156265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
15635d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // Check the shared function info. Make sure it hasn't changed.
15645d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    __ Move(rax, Handle<SharedFunctionInfo>(function->shared()));
15655d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax);
156665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
1567c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    __ Cmp(rdi, function);
156865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
1569c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ j(not_equal, miss);
15705d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org}
157165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
157265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1573394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.comvoid CallStubCompiler::GenerateMissBranch() {
1574394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Handle<Code> code =
157540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org      isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
157640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                                               kind_,
1577ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org                                               extra_state());
1578394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ Jump(code, RelocInfo::CODE_TARGET);
1579394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
1580394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1581394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1582394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.comHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
1583394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                                Handle<JSObject> holder,
1584eeb44b681a16e45f1415dfacff0ba3dba9de5d8cyangguo@chromium.org                                                PropertyIndex index,
1585750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                Handle<Name> name) {
158665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label miss;
15875d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
1588cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  Register reg = HandlerFrontendHeader(
1589cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      object, holder, name, RECEIVER_MAP_CHECK, &miss);
159065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
159157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder),
159257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                           index.translate(holder), Representation::Tagged());
15938a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateJumpFunction(object, rdi, &miss);
159430ce411529579186181838984710b0b0980857aaricow@chromium.org
1595cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
159665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
159765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Return the generated code.
15989af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(Code::FAST, name);
159965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
1600ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
1601ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org
16021510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgHandle<Code> CallStubCompiler::CompileArrayCodeCall(
16031510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<Object> object,
16041510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<JSObject> holder,
16051510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<Cell> cell,
16061510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<JSFunction> function,
16071510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
16081510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
16091510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  Label miss;
16101510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
1611cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1612cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  if (!cell.is_null()) {
16131510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    ASSERT(cell->value() == *function);
16141510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    GenerateLoadFunctionFromCell(cell, function, &miss);
16151510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  }
16161510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
1617bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
1618b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  site->SetElementsKind(GetInitialFastElementsKind());
1619bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
1620cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  const int argc = arguments().immediate();
16211510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ movq(rax, Immediate(argc));
1622bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ Move(rbx, site_feedback_cell);
16231510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ Move(rdi, function);
16241510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
16251510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ArrayConstructorStub stub(isolate());
16261510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ TailCallStub(&stub);
16271510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
1628cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
16291510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
16301510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Return the generated code.
16311510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
16321510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org}
16331510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
16341510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
1635c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileArrayPushCall(
1636c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
1637c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
163841728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    Handle<Cell> cell,
1639c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
16401510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
16411510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
16428a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // If object is not an array or is observed or sealed, bail out to regular
16438a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // call.
1644b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  if (!object->IsJSArray() ||
1645b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org      !cell.is_null() ||
16468a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org      Handle<JSArray>::cast(object)->map()->is_observed() ||
16478a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org      !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1648b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    return Handle<Code>::null();
1649b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  }
16502ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
16512ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  Label miss;
1652cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org
1653cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
16542ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
16555d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  const int argc = arguments().immediate();
1656662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  StackArgumentsAccessor args(rsp, argc);
16575d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  if (argc == 0) {
16585d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    // Noop, return the length.
16595d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
16605d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    __ ret((argc + 1) * kPointerSize);
16612ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  } else {
16625d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    Label call_builtin;
16632ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
16645d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    if (argc == 1) {  // Otherwise fall through to call builtin.
1665fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      Label attempt_to_grow_elements, with_write_barrier, check_double;
16662ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
166778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      // Get the elements array of the object.
166878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ movq(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
166978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org
167078d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      // Check that the elements are in fast mode and writable.
167178d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
167278d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org             factory()->fixed_array_map());
1673fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ j(not_equal, &check_double);
167478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org
16755d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      // Get the array's length into rax and calculate new length.
16765d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
16775d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
16785d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ addl(rax, Immediate(argc));
16792ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
168078d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      // Get the elements' length into rcx.
168178d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
16822ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
16835d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      // Check if we could survive without allocation.
16845d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ cmpl(rax, rcx);
16855d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ j(greater, &attempt_to_grow_elements);
16865d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
1687c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Check if value is a smi.
1688662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org      __ movq(rcx, args.GetArgumentOperand(1));
1689c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ JumpIfNotSmi(rcx, &with_write_barrier);
1690c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
16915d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      // Save new length.
16925d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
16935d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
169478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      // Store the value.
169578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ movq(FieldOperand(rdi,
169678d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org                           rax,
169778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org                           times_pointer_size,
169878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org                           FixedArray::kHeaderSize - argc * kPointerSize),
169978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org              rcx);
17005d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
17015d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ Integer32ToSmi(rax, rax);  // Return new length as smi.
17025d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ ret((argc + 1) * kPointerSize);
17035d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
1704fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ bind(&check_double);
1705fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
1706fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      // Check that the elements are in double mode.
1707fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
1708fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org             factory()->fixed_double_array_map());
1709fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ j(not_equal, &call_builtin);
1710fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
1711fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      // Get the array's length into rax and calculate new length.
1712fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
1713fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
1714fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ addl(rax, Immediate(argc));
1715fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
1716fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      // Get the elements' length into rcx.
1717fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
1718fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
1719fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      // Check if we could survive without allocation.
1720fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ cmpl(rax, rcx);
1721fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ j(greater, &call_builtin);
1722fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
1723662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org      __ movq(rcx, args.GetArgumentOperand(1));
1724fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ StoreNumberToDoubleElements(
1725fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org          rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize);
1726fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
1727fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      // Save new length.
1728fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1729fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ Integer32ToSmi(rax, rax);  // Return new length as smi.
1730fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ ret((argc + 1) * kPointerSize);
1731fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
17325d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ bind(&with_write_barrier);
17335d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
173478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
173578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org
173678d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      if (FLAG_smi_only_arrays  && !FLAG_trace_elements_transitions) {
173778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        Label fast_object, not_fast_object;
173878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        __ CheckFastObjectElements(rbx, &not_fast_object, Label::kNear);
173978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        __ jmp(&fast_object);
174078d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        // In case of fast smi-only, convert to fast object, otherwise bail out.
174178d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        __ bind(&not_fast_object);
1742830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        __ CheckFastSmiElements(rbx, &call_builtin);
1743fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset),
1744fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org               factory()->heap_number_map());
1745fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        __ j(equal, &call_builtin);
174678d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        // rdx: receiver
174778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        // rbx: map
1748830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org
1749830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        Label try_holey_map;
1750830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
175178d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org                                               FAST_ELEMENTS,
175278d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org                                               rbx,
175365a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org                                               rdi,
1754830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                               &try_holey_map);
1755830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org
1756830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        ElementsTransitionGenerator::
175746a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org            GenerateMapChangeElementsTransition(masm(),
175846a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org                                                DONT_TRACK_ALLOCATION_SITE,
175946a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org                                                NULL);
1760830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        // Restore edi.
1761830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        __ movq(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
1762830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        __ jmp(&fast_object);
1763830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org
1764830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        __ bind(&try_holey_map);
1765830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
1766830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                               FAST_HOLEY_ELEMENTS,
1767830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                               rbx,
1768830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                               rdi,
176978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org                                               &call_builtin);
1770830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        ElementsTransitionGenerator::
177146a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org            GenerateMapChangeElementsTransition(masm(),
177246a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org                                                DONT_TRACK_ALLOCATION_SITE,
177346a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org                                                NULL);
1774830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        __ movq(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
177578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        __ bind(&fast_object);
177678d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      } else {
177778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        __ CheckFastObjectElements(rbx, &call_builtin);
177878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      }
177978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org
1780c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Save new length.
1781c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
17825d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
178378d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      // Store the value.
178478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ lea(rdx, FieldOperand(rdi,
1785c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                               rax, times_pointer_size,
1786c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                               FixedArray::kHeaderSize - argc * kPointerSize));
1787c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ movq(Operand(rdx, 0), rcx);
1788c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
178978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ RecordWrite(rdi, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
1790c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                     OMIT_SMI_CHECK);
1791c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1792c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Integer32ToSmi(rax, rax);  // Return new length as smi.
17935d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ ret((argc + 1) * kPointerSize);
17945d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
17955d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ bind(&attempt_to_grow_elements);
17965d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      if (!FLAG_inline_new) {
17975d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org        __ jmp(&call_builtin);
17985d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      }
17995d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
1800662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org      __ movq(rbx, args.GetArgumentOperand(1));
1801a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org      // Growing elements that are SMI-only requires special handling in case
1802a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org      // the new element is non-Smi. For now, delegate to the builtin.
1803a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org      Label no_fast_elements_check;
180478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ JumpIfSmi(rbx, &no_fast_elements_check);
1805394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
1806394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar);
1807a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org      __ bind(&no_fast_elements_check);
1808c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
18095d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      ExternalReference new_space_allocation_top =
18107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          ExternalReference::new_space_allocation_top_address(isolate());
18115d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      ExternalReference new_space_allocation_limit =
18127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          ExternalReference::new_space_allocation_limit_address(isolate());
18135d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
18145d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      const int kAllocationDelta = 4;
18155d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      // Load top.
1816ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      __ Load(rcx, new_space_allocation_top);
18175d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
18185d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      // Check if it's the end of elements.
181978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ lea(rdx, FieldOperand(rdi,
18205d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                               rax, times_pointer_size,
18215d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                               FixedArray::kHeaderSize - argc * kPointerSize));
18225d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ cmpq(rdx, rcx);
18235d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ j(not_equal, &call_builtin);
18245d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ addq(rcx, Immediate(kAllocationDelta * kPointerSize));
1825ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      Operand limit_operand =
1826ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org          masm()->ExternalOperand(new_space_allocation_limit);
1827ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      __ cmpq(rcx, limit_operand);
18285d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ j(above, &call_builtin);
18295d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
18305d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      // We fit and could grow elements.
1831ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      __ Store(new_space_allocation_top, rcx);
18325d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
18335d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      // Push the argument...
183478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ movq(Operand(rdx, 0), rbx);
18355d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      // ... and fill the rest with holes.
18365d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
18375d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      for (int i = 1; i < kAllocationDelta; i++) {
18385d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org        __ movq(Operand(rdx, i * kPointerSize), kScratchRegister);
18395d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      }
18405d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
1841c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // We know the elements array is in new space so we don't need the
1842c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // remembered set, but we just pushed a value onto it so we may have to
1843c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // tell the incremental marker to rescan the object that we just grew.  We
1844c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // don't need to worry about the holes because they are in old space and
1845c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // already marked black.
184678d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
1847c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
18485d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      // Restore receiver to rdx as finish sequence assumes it's here.
1849662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org      __ movq(rdx, args.GetReceiverOperand());
18505d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
18515d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      // Increment element's and array's sizes.
185278d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset),
18535d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                        Smi::FromInt(kAllocationDelta));
18545d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
18555d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      // Make new length a smi before returning it.
18565d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ Integer32ToSmi(rax, rax);
18575d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax);
18585d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
18595d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      __ ret((argc + 1) * kPointerSize);
18605d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    }
18615d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
18625d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    __ bind(&call_builtin);
1863ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
18647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                                   isolate()),
18655d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                                 argc + 1,
18665d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                                 1);
18675d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
18682ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
1869cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
18702ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
18712ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  // Return the generated code.
18721510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
1873c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org}
1874c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org
1875c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org
1876c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileArrayPopCall(
1877c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
1878c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
187941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    Handle<Cell> cell,
1880c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
18811510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
18821510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
18838a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // If object is not an array or is observed or sealed, bail out to regular
18848a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // call.
1885b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  if (!object->IsJSArray() ||
1886b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org      !cell.is_null() ||
18878a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org      Handle<JSArray>::cast(object)->map()->is_observed() ||
18888a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org      !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1889b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    return Handle<Code>::null();
1890b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  }
1891f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
18925d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Label miss, return_undefined, call_builtin;
1893f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
1894cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1895f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
18965d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Get the elements array of the object.
18975d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
1898f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
18995d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Check that the elements are in fast mode and writable.
19005d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
19015d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                 Heap::kFixedArrayMapRootIndex);
19025d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ j(not_equal, &call_builtin);
1903f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
19045d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Get the array's length into rcx and calculate new length.
19055d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
19065d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ subl(rcx, Immediate(1));
19075d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ j(negative, &return_undefined);
1908f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
19095d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Get the last element.
19105d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ LoadRoot(r9, Heap::kTheHoleValueRootIndex);
19115d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ movq(rax, FieldOperand(rbx,
19125d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                            rcx, times_pointer_size,
19135d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                            FixedArray::kHeaderSize));
19145d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Check if element is already the hole.
19155d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ cmpq(rax, r9);
19165d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // If so, call slow-case to also check prototypes for value.
19175d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ j(equal, &call_builtin);
1918f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
19195d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Set the array's length.
19205d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
1921f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
19225d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Fill with the hole and return original value.
19235d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ movq(FieldOperand(rbx,
19245d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                       rcx, times_pointer_size,
19255d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org                       FixedArray::kHeaderSize),
19265d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org          r9);
1927cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  const int argc = arguments().immediate();
19285d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ ret((argc + 1) * kPointerSize);
1929f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
19305d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ bind(&return_undefined);
19315d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
19325d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ ret((argc + 1) * kPointerSize);
1933f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
19345d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ bind(&call_builtin);
1935ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ TailCallExternalReference(
19367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      ExternalReference(Builtins::c_ArrayPop, isolate()),
1937ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      argc + 1,
1938ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      1);
1939f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
1940cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
1941f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
1942f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org  // Return the generated code.
19431510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
1944f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org}
1945f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
1946f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
1947c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
1948c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
1949c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
195041728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    Handle<Cell> cell,
1951c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
19521510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
19531510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
19545d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // If object is not a string, bail out to regular call.
1955c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
19562c186ca6690a1cb19ec7584e71f167234587c87cwhesse@chromium.org
19575d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Label miss;
19580511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  Label name_miss;
19595d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Label index_out_of_range;
19600511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  Label* index_out_of_range_label = &index_out_of_range;
196140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  if (kind_ == Code::CALL_IC &&
1962ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      (CallICBase::StringStubState::decode(extra_state()) ==
196340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org       DEFAULT_STRING_STUB)) {
19640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    index_out_of_range_label = &miss;
19650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
1966cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org
1967cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
19680b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
19695d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Register receiver = rbx;
19705d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Register index = rdi;
19715d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Register result = rax;
1972cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  const int argc = arguments().immediate();
1973cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  StackArgumentsAccessor args(rsp, argc);
1974cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org
1975662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ movq(receiver, args.GetReceiverOperand());
19765d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  if (argc > 0) {
1977662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org    __ movq(index, args.GetArgumentOperand(1));
19785d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  } else {
19795d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
19805d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
19810b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
1982c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  StringCharCodeAtGenerator generator(receiver,
1983c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                      index,
1984c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                      result,
1985c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                      &miss,  // When not a string.
1986c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                      &miss,  // When not a number.
1987c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                      index_out_of_range_label,
1988c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                      STRING_INDEX_IS_NUMBER);
1989c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  generator.GenerateFast(masm());
19905d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ ret((argc + 1) * kPointerSize);
19910b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
19925d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  StubRuntimeCallHelper call_helper;
1993c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  generator.GenerateSlow(masm(), call_helper);
19940b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
19950511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (index_out_of_range.is_linked()) {
19960511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    __ bind(&index_out_of_range);
19970511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    __ LoadRoot(rax, Heap::kNanValueRootIndex);
19980511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    __ ret((argc + 1) * kPointerSize);
19990511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
20000b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
20010b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  __ bind(&miss);
20020511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Restore function name in rcx.
2003c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ Move(rcx, name);
20048a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  HandlerFrontendFooter(&name_miss);
20050b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
20060b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Return the generated code.
20071510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
20085aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
20095aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
20105aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
2011c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileStringCharAtCall(
2012c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
2013c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
201441728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    Handle<Cell> cell,
2015c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
20161510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
20171510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
20185d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // If object is not a string, bail out to regular call.
2019c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
20205d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
20215d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  const int argc = arguments().immediate();
2022662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  StackArgumentsAccessor args(rsp, argc);
2023662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org
2024e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  Label miss;
20250511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  Label name_miss;
20265d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Label index_out_of_range;
20270511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  Label* index_out_of_range_label = &index_out_of_range;
202840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  if (kind_ == Code::CALL_IC &&
2029ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      (CallICBase::StringStubState::decode(extra_state()) ==
203040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org       DEFAULT_STRING_STUB)) {
20310511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    index_out_of_range_label = &miss;
20320511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
2033cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org
2034cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
2035e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
20365d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Register receiver = rax;
20375d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Register index = rdi;
2038c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  Register scratch = rdx;
20395d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Register result = rax;
2040662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ movq(receiver, args.GetReceiverOperand());
20415d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  if (argc > 0) {
2042662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org    __ movq(index, args.GetArgumentOperand(1));
20435d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  } else {
20445d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
2045e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
2046e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
2047c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  StringCharAtGenerator generator(receiver,
2048c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                  index,
2049c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org                                  scratch,
2050c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                  result,
2051c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                  &miss,  // When not a string.
2052c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                  &miss,  // When not a number.
2053c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                  index_out_of_range_label,
2054c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                  STRING_INDEX_IS_NUMBER);
2055c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  generator.GenerateFast(masm());
20565d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ ret((argc + 1) * kPointerSize);
20575d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
20585d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  StubRuntimeCallHelper call_helper;
2059c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  generator.GenerateSlow(masm(), call_helper);
2060e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
20610511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  if (index_out_of_range.is_linked()) {
20620511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    __ bind(&index_out_of_range);
20634a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ LoadRoot(rax, Heap::kempty_stringRootIndex);
20640511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com    __ ret((argc + 1) * kPointerSize);
20650511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  }
2066e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  __ bind(&miss);
20670511e24c6ebf94594a7e03bdcd58157ac2971d69erik.corry@gmail.com  // Restore function name in rcx.
2068c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ Move(rcx, name);
20698a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  HandlerFrontendFooter(&name_miss);
2070e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
2071e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Return the generated code.
20721510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
20732abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org}
20742abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org
20752abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org
2076c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
2077c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
2078c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
207941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    Handle<Cell> cell,
2080c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
20811510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
20821510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
20835d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // If the object is not a JSObject or we got an unexpected number of
20845d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // arguments, bail out to the regular call.
2085c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  const int argc = arguments().immediate();
2086662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  StackArgumentsAccessor args(rsp, argc);
2087c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
20885aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
2089e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  Label miss;
2090e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
2091cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2092cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  if (!cell.is_null()) {
2093c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    ASSERT(cell->value() == *function);
20945d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    GenerateLoadFunctionFromCell(cell, function, &miss);
20955d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
20965aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
20975d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Load the char code argument.
20985d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Register code = rbx;
2099d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  __ movq(code, args.GetArgumentOperand(1));
2100c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
21015d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Check the code is a smi.
21025d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Label slow;
21035d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ JumpIfNotSmi(code, &slow);
2104c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
21055d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Convert the smi code to uint16.
21065d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ SmiAndConstant(code, code, Smi::FromInt(0xffff));
2107c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
2108c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  StringCharFromCodeGenerator generator(code, rax);
2109c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  generator.GenerateFast(masm());
21105d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ ret(2 * kPointerSize);
2111c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
21125d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  StubRuntimeCallHelper call_helper;
2113c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  generator.GenerateSlow(masm(), call_helper);
21145d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
21155d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ bind(&slow);
21168a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // We do not have to patch the receiver because the function makes no use of
21178a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // it.
21188a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateJumpFunctionIgnoreReceiver(function);
2119c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
2120cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
2121c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
2122c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  // Return the generated code.
21231510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
2124c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org}
2125c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
2126c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
2127c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileMathFloorCall(
2128c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
2129c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
213041728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    Handle<Cell> cell,
2131c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
21321510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
21331510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
21341e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  const int argc = arguments().immediate();
2135d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  StackArgumentsAccessor args(rsp, argc);
21361e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
21371e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // If the object is not a JSObject or we got an unexpected number of
21381e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // arguments, bail out to the regular call.
21391e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  if (!object->IsJSObject() || argc != 1) {
21401e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    return Handle<Code>::null();
21411e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  }
21421e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
2143cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  Label miss, slow;
21441e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
2145cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2146cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  if (!cell.is_null()) {
21471e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    ASSERT(cell->value() == *function);
21481e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    GenerateLoadFunctionFromCell(cell, function, &miss);
21491e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  }
21501e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
21511e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Load the (only) argument into rax.
2152d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  __ movq(rax, args.GetArgumentOperand(1));
21531e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
21541e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Check if the argument is a smi.
21551e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  Label smi;
21561e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
21571e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ JumpIfSmi(rax, &smi);
21581e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
21591e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Check if the argument is a heap number and load its value into xmm0.
21601e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
21611e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
21621e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
21631e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Check if the argument is strictly positive. Note this also discards NaN.
21641e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ xorpd(xmm1, xmm1);
21651e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ ucomisd(xmm0, xmm1);
21661e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ j(below_equal, &slow);
21671e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
21681e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Do a truncating conversion.
21691e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ cvttsd2si(rax, xmm0);
21701e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
21711e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Checks for 0x80000000 which signals a failed conversion.
21721e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  Label conversion_failure;
21731e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ cmpl(rax, Immediate(0x80000000));
21741e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ j(equal, &conversion_failure);
21751e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
21761e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Smi tag and return.
21771e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ Integer32ToSmi(rax, rax);
21781e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ bind(&smi);
21791e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ ret(2 * kPointerSize);
21801e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
21811e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Check if the argument is < 2^kMantissaBits.
21821e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  Label already_round;
21831e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ bind(&conversion_failure);
21841e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  int64_t kTwoMantissaBits= V8_INT64_C(0x4330000000000000);
2185e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  __ movq(rbx, kTwoMantissaBits);
21861e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ movq(xmm1, rbx);
21871e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ ucomisd(xmm0, xmm1);
21881e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ j(above_equal, &already_round);
21891e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
21901e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Save a copy of the argument.
21911e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ movaps(xmm2, xmm0);
21921e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
21931e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits.
21941e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ addsd(xmm0, xmm1);
21951e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ subsd(xmm0, xmm1);
21961e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
21971e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Compare the argument and the tentative result to get the right mask:
21981e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   if xmm2 < xmm0:
21991e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //     xmm2 = 1...1
22001e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   else:
22011e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //     xmm2 = 0...0
22021e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ cmpltsd(xmm2, xmm0);
22031e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
22041e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Subtract 1 if the argument was less than the tentative result.
22051e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  int64_t kOne = V8_INT64_C(0x3ff0000000000000);
2206e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  __ movq(rbx, kOne);
22071e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ movq(xmm1, rbx);
22081e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ andpd(xmm1, xmm2);
22091e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ subsd(xmm0, xmm1);
22101e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
22111e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Return a new heap number.
22121e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ AllocateHeapNumber(rax, rbx, &slow);
22131e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0);
22141e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ ret(2 * kPointerSize);
22151e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
22161e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Return the argument (when it's an already round heap number).
22171e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ bind(&already_round);
2218d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  __ movq(rax, args.GetArgumentOperand(1));
22191e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ ret(2 * kPointerSize);
22201e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
22211e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ bind(&slow);
22228a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // We do not have to patch the receiver because the function makes no use of
22238a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // it.
22248a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateJumpFunctionIgnoreReceiver(function);
22251e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
2226cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
22271e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
22281e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Return the generated code.
22291e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  return GetCode(type, name);
22305aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
22315aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
22325aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
2233c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileMathAbsCall(
2234c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
2235c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
223641728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    Handle<Cell> cell,
2237c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
22381510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
22391510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
22405d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // If the object is not a JSObject or we got an unexpected number of
22415d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // arguments, bail out to the regular call.
2242c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  const int argc = arguments().immediate();
2243662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  StackArgumentsAccessor args(rsp, argc);
2244c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
22455d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
22460b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  Label miss;
22470b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2248cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2249cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  if (!cell.is_null()) {
2250c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    ASSERT(cell->value() == *function);
22515d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    GenerateLoadFunctionFromCell(cell, function, &miss);
22525d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
2253cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org
22545d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Load the (only) argument into rax.
2255d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  __ movq(rax, args.GetArgumentOperand(1));
22565aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
22575d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Check if the argument is a smi.
22585d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Label not_smi;
22595d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  STATIC_ASSERT(kSmiTag == 0);
22605d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ JumpIfNotSmi(rax, &not_smi);
22615aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
2262594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // Branchless abs implementation, refer to below:
2263594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs
22645d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
22655d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // otherwise.
2266594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ movq(rbx, rax);
2267594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ sar(rbx, Immediate(kBitsPerPointer - 1));
2268e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
22695d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Do bitwise not or do nothing depending on ebx.
2270594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ xor_(rax, rbx);
2271e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
22725d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Add 1 or do nothing depending on ebx.
2273594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ subq(rax, rbx);
22745d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
22755d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // If the result is still negative, go to the slow case.
22765d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // This only happens for the most negative smi.
22775d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Label slow;
22785d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ j(negative, &slow);
22795d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
22805d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ ret(2 * kPointerSize);
22815d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
22825d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Check if the argument is a heap number and load its value.
22835d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ bind(&not_smi);
2284c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
2285e94b5ff1e1e95fb2c8ef6bce66ce8533786d9792bmeurer@chromium.org  __ MoveDouble(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
2286e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
22875d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Check the sign of the argument. If the argument is positive,
22885d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // just return it.
22895d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  Label negative_sign;
22905d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  const int sign_mask_shift =
22915d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      (HeapNumber::kExponentOffset - HeapNumber::kValueOffset) * kBitsPerByte;
2292e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  __ Set(rdi, static_cast<int64_t>(HeapNumber::kSignMask) << sign_mask_shift);
22935d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ testq(rbx, rdi);
22945d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ j(not_zero, &negative_sign);
22955d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ ret(2 * kPointerSize);
2296e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
22975d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // If the argument is negative, clear the sign, and return a new
22985d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // number. We still have the sign mask in rdi.
22995d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ bind(&negative_sign);
23005d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ xor_(rbx, rdi);
23015d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ AllocateHeapNumber(rax, rdx, &slow);
2302e94b5ff1e1e95fb2c8ef6bce66ce8533786d9792bmeurer@chromium.org  __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx);
23035d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ ret(2 * kPointerSize);
2304e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
23055d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ bind(&slow);
23068a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // We do not have to patch the receiver because the function makes no use of
23078a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // it.
23088a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateJumpFunctionIgnoreReceiver(function);
2309e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
2310cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
2311e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
2312e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Return the generated code.
23131510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
23142abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org}
23152abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org
23162abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org
2317c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileFastApiCall(
2318ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    const CallOptimization& optimization,
2319c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
2320c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
232141728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    Handle<Cell> cell,
2322c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
2323c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<String> name) {
2324ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ASSERT(optimization.is_simple_api_call());
2325ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Bail out if object is a global object as we don't want to
2326ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // repatch it to global receiver.
2327c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (object->IsGlobalObject()) return Handle<Code>::null();
2328c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (!cell.is_null()) return Handle<Code>::null();
2329c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (!object->IsJSObject()) return Handle<Code>::null();
2330ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  int depth = optimization.GetPrototypeDepthOfExpectedType(
2331c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      Handle<JSObject>::cast(object), holder);
2332c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (depth == kInvalidProtoDepth) return Handle<Code>::null();
2333ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
2334ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Label miss, miss_before_stack_reserved;
2335c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  GenerateNameCheck(name, &miss_before_stack_reserved);
2336ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
2337ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  const int argc = arguments().immediate();
2338662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  StackArgumentsAccessor args(rsp, argc);
2339662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ movq(rdx, args.GetReceiverOperand());
2340ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
2341ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Check that the receiver isn't a smi.
2342ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ JumpIfSmi(rdx, &miss_before_stack_reserved);
2343ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
23447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Counters* counters = isolate()->counters();
23457979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->call_const(), 1);
23467979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->call_const_fast_api(), 1);
2347ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
2348ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Allocate space for v8::Arguments implicit values. Must be initialized
2349ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // before calling any runtime function.
2350ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
2351ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
2352ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Check that the maps haven't changed and find a Holder as a side effect.
2353f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
2354f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                  rbx, rax, rdi, name, depth, &miss);
2355ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
2356ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Move the return address on top of the stack.
2357d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org  __ movq(rax,
2358d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org          StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize));
2359d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org  __ movq(StackOperandForReturnAddress(0), rax);
2360ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
23617ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  GenerateFastApiCall(masm(), optimization, argc);
2362ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
2363ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ bind(&miss);
2364ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
2365ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
23668a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  HandlerFrontendFooter(&miss_before_stack_reserved);
2367ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
2368ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Return the generated code.
2369c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  return GetCode(function);
2370ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org}
2371ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
2372ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
2373b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.orgvoid StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
2374b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  Label success;
2375b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  // Check that the object is a boolean.
2376b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  __ CompareRoot(object, Heap::kTrueValueRootIndex);
2377b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  __ j(equal, &success);
2378b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  __ CompareRoot(object, Heap::kFalseValueRootIndex);
2379b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  __ j(not_equal, miss);
2380b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  __ bind(&success);
2381b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org}
2382b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org
2383b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org
2384cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.orgvoid CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
2385cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  if (object->IsGlobalObject()) {
2386cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org    StackArgumentsAccessor args(rsp, arguments());
2387cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
2388cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org    __ movq(args.GetReceiverOperand(), rdx);
2389cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  }
2390cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org}
2391cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org
2392cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org
2393cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.orgRegister CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
2394cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org                                                 Handle<JSObject> holder,
2395cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org                                                 Handle<Name> name,
2396cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org                                                 CheckType check,
2397cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org                                                 Label* miss) {
2398cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  GenerateNameCheck(name, miss);
2399cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org
2400cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  Register reg = rdx;
24010b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2402662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  StackArgumentsAccessor args(rsp, arguments());
2403cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  __ movq(reg, args.GetReceiverOperand());
24040b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
24055d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Check that the receiver isn't a smi.
24065d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  if (check != NUMBER_CHECK) {
2407cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org    __ JumpIfSmi(reg, miss);
24085d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
24090b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
24105d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Make sure that it's okay not to patch the on stack receiver
24115d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // unless we're doing a receiver map check.
24125d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
24130b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
24147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Counters* counters = isolate()->counters();
24155d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  switch (check) {
24165d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    case RECEIVER_MAP_CHECK:
24177979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org      __ IncrementCounter(counters->call_const(), 1);
24180b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
24195d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      // Check that the maps haven't changed.
2420cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder,
2421cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org                            rbx, rax, rdi, name, miss);
24225d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      break;
24230b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2424f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    case STRING_CHECK: {
24254a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      // Check that the object is a string.
2426cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, rax);
2427cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ j(above_equal, miss);
24282f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      // Check that the maps starting from the prototype haven't changed.
24292f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      GenerateDirectLoadGlobalFunctionPrototype(
2430cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org          masm(), Context::STRING_FUNCTION_INDEX, rax, miss);
2431c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      break;
2432f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    }
2433f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    case SYMBOL_CHECK: {
24344a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      // Check that the object is a symbol.
2435cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ CmpObjectType(reg, SYMBOL_TYPE, rax);
2436cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ j(not_equal, miss);
2437f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      // Check that the maps starting from the prototype haven't changed.
2438f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      GenerateDirectLoadGlobalFunctionPrototype(
2439cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org          masm(), Context::SYMBOL_FUNCTION_INDEX, rax, miss);
24404a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      break;
2441f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    }
24422f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org    case NUMBER_CHECK: {
24432f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      Label fast;
24442f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      // Check that the object is a smi or a heap number.
2445cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ JumpIfSmi(reg, &fast);
2446cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ CmpObjectType(reg, HEAP_NUMBER_TYPE, rax);
2447cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ j(not_equal, miss);
24482f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      __ bind(&fast);
24492f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      // Check that the maps starting from the prototype haven't changed.
24502f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      GenerateDirectLoadGlobalFunctionPrototype(
2451cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org          masm(), Context::NUMBER_FUNCTION_INDEX, rax, miss);
2452c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      break;
24532f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org    }
24542f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org    case BOOLEAN_CHECK: {
2455cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      GenerateBooleanCheck(reg, miss);
24562f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      // Check that the maps starting from the prototype haven't changed.
24572f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      GenerateDirectLoadGlobalFunctionPrototype(
2458cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org          masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, miss);
24595d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org      break;
24602f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org    }
24615d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
24620b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2463cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  if (check != RECEIVER_MAP_CHECK) {
2464cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org    Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
2465cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org    reg = CheckPrototypes(
2466cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org        IC::CurrentTypeOf(prototype, isolate()),
2467cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org        rax, holder, rbx, rdx, rdi, name, miss);
2468cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  }
2469b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org
2470cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  return reg;
24712f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org}
24722f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org
24732f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org
24748a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.orgvoid CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
24758a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                                            Register function,
24768a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                                            Label* miss) {
24778a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // Check that the function really is a function.
24788a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateFunctionCheck(function, rbx, miss);
24792f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org
24808a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  if (!function.is(rdi)) __ movq(rdi, function);
2481cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  PatchGlobalProxy(object);
24820b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
24838a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // Invoke the function.
24848a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
24858a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                    NullCallWrapper(), call_kind());
24860b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org}
24870b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
24880b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2489c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
2490c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                                      Handle<JSObject> holder,
2491750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Handle<Name> name) {
24920b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  Label miss;
2493c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  GenerateNameCheck(name, &miss);
24940b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2495394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  LookupResult lookup(isolate());
24960b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  LookupPostInterceptor(holder, name, &lookup);
24975d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
24985d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Get the receiver from the stack.
2499662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  StackArgumentsAccessor args(rsp, arguments());
2500662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ movq(rdx, args.GetReceiverOperand());
25015d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
2502ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state());
2503c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax,
2504c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                   &miss);
25055d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
25065d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Restore receiver.
2507662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ movq(rdx, args.GetReceiverOperand());
25085d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
25098a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateJumpFunction(object, rax, &miss);
25105d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
25118a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  HandlerFrontendFooter(&miss);
25120b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
25130b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Return the generated code.
25149af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(Code::FAST, name);
25150b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org}
25160b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
25170b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2518c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileCallGlobal(
2519c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> object,
2520c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<GlobalObject> holder,
2521b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    Handle<PropertyCell> cell,
2522c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
2523750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    Handle<Name> name) {
2524ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (HasCustomCallGenerator(function)) {
2525750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    Handle<Code> code = CompileCustomCall(
25261510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org        object, holder, cell, function, Handle<String>::cast(name),
25271510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org        Code::NORMAL);
2528c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    // A null handle means bail out to the regular compiler code below.
2529c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    if (!code.is_null()) return code;
25305d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
25315d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
25320b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  Label miss;
2533cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
25348a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // Potentially loads a closure that matches the shared function info of the
25358a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // function, rather than function.
25365d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  GenerateLoadFunctionFromCell(cell, function, &miss);
25377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Counters* counters = isolate()->counters();
25387979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->call_global_inline(), 1);
25398a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateJumpFunction(object, rdi, function);
2540cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
25410b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
25420b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Return the generated code.
25437a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  return GetCode(Code::NORMAL, name);
25440b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org}
25450b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
25460b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2547394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.comHandle<Code> StoreStubCompiler::CompileStoreCallback(
25482bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    Handle<JSObject> object,
2549355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    Handle<JSObject> holder,
2550bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Handle<Name> name,
25517c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org    Handle<ExecutableAccessorInfo> callback) {
2552f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  HandlerFrontend(IC::CurrentTypeOf(object, isolate()),
2553f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                  receiver(), holder, name);
25540b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
2555594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ PopReturnAddressTo(scratch1());
25562bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ push(receiver());
2557394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ Push(callback);  // callback info
2558bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ Push(name);
25592bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ push(value());
2560594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ PushReturnAddressFrom(scratch1());
25615d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
25625d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Do tail-call to the runtime system.
25635d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  ExternalReference store_callback_property =
25647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
25655d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ TailCallExternalReference(store_callback_property, 4, 1);
2566e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
2567e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Return the generated code.
25689af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
2569639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org}
2570639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
2571639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
2572639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.orgHandle<Code> StoreStubCompiler::CompileStoreCallback(
2573639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    Handle<JSObject> object,
2574639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    Handle<JSObject> holder,
2575639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    Handle<Name> name,
2576639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    const CallOptimization& call_optimization) {
2577f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  HandlerFrontend(IC::CurrentTypeOf(object, isolate()),
2578f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                  receiver(), holder, name);
2579639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
2580639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  Register values[] = { value() };
2581639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  GenerateFastApiCall(
25827ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org      masm(), call_optimization, receiver(), scratch1(),
25837ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org      scratch2(), this->name(), 1, values);
2584639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
2585639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  // Return the generated code.
25869af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
25875aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
25885aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
25895aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
259046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#undef __
259146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#define __ ACCESS_MASM(masm)
259246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
259346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
259446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.orgvoid StoreStubCompiler::GenerateStoreViaSetter(
259546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    MacroAssembler* masm,
2596619781ad24991bca2894d2f677ac960da366b11esvenpanne@chromium.org    Handle<JSFunction> setter) {
25977028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // ----------- S t a t e -------------
25987028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  //  -- rax    : value
25997028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  //  -- rcx    : name
26007028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  //  -- rdx    : receiver
26017028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  //  -- rsp[0] : return address
26027028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // -----------------------------------
26037028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  {
260446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
26057028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
26067028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // Save value register, so we can restore it later.
26077028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ push(rax);
26087028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
260946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    if (!setter.is_null()) {
261046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      // Call the JavaScript setter with receiver and value on the stack.
261146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      __ push(rdx);
261246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      __ push(rax);
261346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      ParameterCount actual(1);
261432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ParameterCount expected(setter);
261532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      __ InvokeFunction(setter, expected, actual,
261632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                        CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
261746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    } else {
261846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      // If we generate a global code snippet for deoptimization only, remember
261946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      // the place to continue after deoptimization.
262046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
262146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    }
26227028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
26237028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // We have to return the passed value, not the return value of the setter.
26247028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ pop(rax);
26257028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
26267028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // Restore context register.
26277028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
26287028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  }
26297028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  __ ret(0);
263046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org}
263146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
263246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
263346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#undef __
263446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#define __ ACCESS_MASM(masm())
263546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
263646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
2637394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.comHandle<Code> StoreStubCompiler::CompileStoreInterceptor(
26382bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    Handle<JSObject> object,
2639750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    Handle<Name> name) {
2640594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ PopReturnAddressTo(scratch1());
26412bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ push(receiver());
26422bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ push(this->name());
26432bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ push(value());
2644594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ PushReturnAddressFrom(scratch1());
26450b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
26460b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Do tail-call to the runtime system.
26470b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  ExternalReference store_ic_property =
26487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
2649cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  __ TailCallExternalReference(store_ic_property, 3, 1);
26500b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
26510b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  // Return the generated code.
26529af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
26535aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org}
26545aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
26555aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org
2656394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.comHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
2657394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    MapHandleList* receiver_maps,
2658394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    CodeHandleList* handler_stubs,
2659394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    MapHandleList* transitioned_maps) {
2660ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  Label miss;
26612bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ JumpIfSmi(receiver(), &miss, Label::kNear);
2662a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
26632bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ movq(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset));
2664ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  int receiver_count = receiver_maps->length();
2665b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  for (int i = 0; i < receiver_count; ++i) {
2666ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org    // Check map and tail call if there's a match
26672bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    __ Cmp(scratch1(), receiver_maps->at(i));
2668394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    if (transitioned_maps->at(i).is_null()) {
2669394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET);
2670b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org    } else {
2671b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      Label next_map;
2672b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ j(not_equal, &next_map, Label::kNear);
26732bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org      __ movq(transition_map(),
26742bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org              transitioned_maps->at(i),
26752bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org              RelocInfo::EMBEDDED_OBJECT);
2676394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
2677b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ bind(&next_map);
2678b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org    }
2679a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
2680a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2681a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&miss);
26822bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
26832bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  TailCallBuiltin(masm(), MissBuiltin(kind()));
2684a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2685a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Return the generated code.
26862bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  return GetICCode(
26872bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org      kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
2688a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
2689a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2690a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2691f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type,
2692f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                                      Handle<JSObject> last,
2693f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                                      Handle<Name> name) {
2694f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  NonexistentHandlerFrontend(type, last, name);
269530ce411529579186181838984710b0b0980857aaricow@chromium.org
26965d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Return undefined if maps of the full prototype chain are still the
26975d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // same and no global property with this name contains a value.
26985d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
26995d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ ret(0);
27005d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
27015d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Return the generated code.
27029af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
27035d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org}
27045d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
27055d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
270694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.orgRegister* LoadStubCompiler::registers() {
270794b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  // receiver, name, scratch1, scratch2, scratch3, scratch4.
27082f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org  static Register registers[] = { rax, rcx, rdx, rbx, rdi, r8 };
270994b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  return registers;
271094b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org}
27115d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
27125d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
271394b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.orgRegister* KeyedLoadStubCompiler::registers() {
271494b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  // receiver, name, scratch1, scratch2, scratch3, scratch4.
271594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  static Register registers[] = { rdx, rax, rbx, rcx, rdi, r8 };
271694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  return registers;
27175d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org}
27185d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
27195d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
27202bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.orgRegister* StoreStubCompiler::registers() {
27212bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // receiver, name, value, scratch1, scratch2, scratch3.
27222bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  static Register registers[] = { rdx, rcx, rax, rbx, rdi, r8 };
27232bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  return registers;
27242bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org}
27252bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
27262bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
27272bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.orgRegister* KeyedStoreStubCompiler::registers() {
27282bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // receiver, name, value, scratch1, scratch2, scratch3.
27292bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  static Register registers[] = { rdx, rcx, rax, rbx, rdi, r8 };
27302bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  return registers;
27312bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org}
27322bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
27332bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
2734750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgvoid KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
273594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org                                              Register name_reg,
273694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org                                              Label* miss) {
273794b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  __ Cmp(name_reg, name);
273894b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  __ j(not_equal, miss);
27395d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org}
27405d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
27415d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
27422bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.orgvoid KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
27432bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                                               Register name_reg,
27442bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                                               Label* miss) {
27452bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ Cmp(name_reg, name);
27462bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ j(not_equal, miss);
27472bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org}
27482bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
27492bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
2750de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org#undef __
2751de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org#define __ ACCESS_MASM(masm)
2752de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2753de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2754de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
27552efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                             Register receiver,
2756de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org                                             Handle<JSFunction> getter) {
2757de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  // ----------- S t a t e -------------
2758de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  //  -- rax    : receiver
2759de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  //  -- rcx    : name
2760de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  //  -- rsp[0] : return address
2761de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  // -----------------------------------
2762de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  {
2763de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
2764de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2765de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    if (!getter.is_null()) {
2766de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      // Call the JavaScript getter with the receiver on the stack.
27672efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org      __ push(receiver);
2768de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      ParameterCount actual(0);
276932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ParameterCount expected(getter);
277032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      __ InvokeFunction(getter, expected, actual,
277132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                        CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
2772de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    } else {
2773de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      // If we generate a global code snippet for deoptimization only, remember
2774de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      // the place to continue after deoptimization.
2775de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
2776de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    }
2777de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2778de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    // Restore context register.
2779de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2780de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  }
2781de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  __ ret(0);
2782de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org}
2783de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2784de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2785de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org#undef __
2786de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org#define __ ACCESS_MASM(masm())
2787de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2788de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2789394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.comHandle<Code> LoadStubCompiler::CompileLoadGlobal(
2790f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    Handle<Type> type,
27918432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Handle<GlobalObject> global,
2792b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    Handle<PropertyCell> cell,
2793750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    Handle<Name> name,
2794394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    bool is_dont_delete) {
2795b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  Label miss;
27968432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  // TODO(verwaest): Directly store to rax. Currently we cannot do this, since
27978432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  // rax is used as receiver(), which we would otherwise clobber before a
27988432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  // potential miss.
2799f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  HandlerFrontendHeader(type, receiver(), global, name, &miss);
28005d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
28015d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Get the value from the cell.
2802394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ Move(rbx, cell);
2803b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  __ movq(rbx, FieldOperand(rbx, PropertyCell::kValueOffset));
28045d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
28055d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Check for deleted property if property can actually be deleted.
28065d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  if (!is_dont_delete) {
28075d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
28085d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    __ j(equal, &miss);
28095d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  } else if (FLAG_debug_code) {
28105d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
2811594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
28125d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
28135d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
2814b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  HandlerFrontendFooter(name, &miss);
28158432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org
28167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Counters* counters = isolate()->counters();
28177979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->named_load_global_stub(), 1);
28185d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ movq(rax, rbx);
28195d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ ret(0);
28205d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
28215d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Return the generated code.
2822e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  return GetCode(kind(), Code::NORMAL, name);
28235d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org}
282430ce411529579186181838984710b0b0980857aaricow@chromium.org
282530ce411529579186181838984710b0b0980857aaricow@chromium.org
2826bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgHandle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
2827af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    TypeHandleList* types,
28284a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    CodeHandleList* handlers,
2829750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    Handle<Name> name,
28304a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Code::StubType type,
28314a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    IcCheckType check) {
2832ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  Label miss;
2833e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
28344a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  if (check == PROPERTY) {
28354a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    GenerateNameCheck(name, this->name(), &miss);
28364a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  }
28374a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
2838b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  Label number_case;
2839af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
2840b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  __ JumpIfSmi(receiver(), smi_target);
2841b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org
28424a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Register map_reg = scratch1();
28434a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ movq(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
2844af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  int receiver_count = types->length();
2845f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  int number_of_handled_maps = 0;
2846ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  for (int current = 0; current < receiver_count; ++current) {
2847af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    Handle<Type> type = types->at(current);
2848af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    Handle<Map> map = IC::TypeToMap(*type, isolate());
2849f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    if (!map->is_deprecated()) {
2850f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      number_of_handled_maps++;
2851f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Check map and tail call if there's a match
2852af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      __ Cmp(map_reg, map);
2853af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      if (type->Is(Type::Number())) {
2854b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org        ASSERT(!number_case.is_unused());
2855b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org        __ bind(&number_case);
2856b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org      }
2857f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET);
2858f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
2859ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  }
2860f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  ASSERT(number_of_handled_maps > 0);
28615d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
2862ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org  __  bind(&miss);
28632bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  TailCallBuiltin(masm(), MissBuiltin(kind()));
28645d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
28655d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // Return the generated code.
28664a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  InlineCacheState state =
2867f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC;
2868750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  return GetICCode(kind(), type, name, state);
2869e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org}
2870e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
2871e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
2872ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org#undef __
2873ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org#define __ ACCESS_MASM(masm)
2874ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org
2875ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org
28766db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.orgvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
28776db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    MacroAssembler* masm) {
28786db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // ----------- S t a t e -------------
28796db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- rax    : key
28806db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- rdx    : receiver
28816db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- rsp[0] : return address
28826db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // -----------------------------------
2883af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  Label slow, miss;
28846db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
28856db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // This stub is meant to be tail-jumped to, the receiver must already
28866db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // have been verified by the caller to not be a smi.
28876db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
2888af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  __ JumpIfNotSmi(rax, &miss);
28896db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ SmiToInteger32(rbx, rax);
28906db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
28916db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
28926db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Check whether the elements is a number dictionary.
28936db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // rdx: receiver
28946db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // rax: key
28956db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // rbx: key as untagged int32
28966db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // rcx: elements
28976db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax);
28986db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ ret(0);
28996db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
29006db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ bind(&slow);
29016db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // ----------- S t a t e -------------
29026db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- rax    : key
29036db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- rdx    : receiver
2904c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  //  -- rsp[0] : return address
29056db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // -----------------------------------
29062bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
29076db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
2908af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  __ bind(&miss);
29096db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // ----------- S t a t e -------------
29106db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- rax    : key
29116db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- rdx    : receiver
2912c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  //  -- rsp[0] : return address
29136db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // -----------------------------------
2914af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
29156db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org}
29166db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
291728faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org
2918e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org#undef __
2919e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
29205aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org} }  // namespace v8::internal
29219dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
29229dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif  // V8_TARGET_ARCH_X64
2923