105ed9ddc6ff3a1ab3983c50d378cddfa257869b6jkummerow@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
25c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Redistribution and use in source and binary forms, with or without
35c838251403b0be9a882540f1922577abba4c872ager@chromium.org// modification, are permitted provided that the following conditions are
45c838251403b0be9a882540f1922577abba4c872ager@chromium.org// met:
55c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
65c838251403b0be9a882540f1922577abba4c872ager@chromium.org//     * Redistributions of source code must retain the above copyright
75c838251403b0be9a882540f1922577abba4c872ager@chromium.org//       notice, this list of conditions and the following disclaimer.
85c838251403b0be9a882540f1922577abba4c872ager@chromium.org//     * Redistributions in binary form must reproduce the above
95c838251403b0be9a882540f1922577abba4c872ager@chromium.org//       copyright notice, this list of conditions and the following
105c838251403b0be9a882540f1922577abba4c872ager@chromium.org//       disclaimer in the documentation and/or other materials provided
115c838251403b0be9a882540f1922577abba4c872ager@chromium.org//       with the distribution.
125c838251403b0be9a882540f1922577abba4c872ager@chromium.org//     * Neither the name of Google Inc. nor the names of its
135c838251403b0be9a882540f1922577abba4c872ager@chromium.org//       contributors may be used to endorse or promote products derived
145c838251403b0be9a882540f1922577abba4c872ager@chromium.org//       from this software without specific prior written permission.
155c838251403b0be9a882540f1922577abba4c872ager@chromium.org//
165c838251403b0be9a882540f1922577abba4c872ager@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175c838251403b0be9a882540f1922577abba4c872ager@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185c838251403b0be9a882540f1922577abba4c872ager@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195c838251403b0be9a882540f1922577abba4c872ager@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205c838251403b0be9a882540f1922577abba4c872ager@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215c838251403b0be9a882540f1922577abba4c872ager@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225c838251403b0be9a882540f1922577abba4c872ager@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235c838251403b0be9a882540f1922577abba4c872ager@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245c838251403b0be9a882540f1922577abba4c872ager@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255c838251403b0be9a882540f1922577abba4c872ager@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265c838251403b0be9a882540f1922577abba4c872ager@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275c838251403b0be9a882540f1922577abba4c872ager@chromium.org
285c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include "v8.h"
295c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3093a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_MIPS
319dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
325c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include "ic-inl.h"
3383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org#include "codegen.h"
345c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include "stub-cache.h"
355c838251403b0be9a882540f1922577abba4c872ager@chromium.org
365c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace v8 {
375c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace internal {
385c838251403b0be9a882540f1922577abba4c872ager@chromium.org
395c838251403b0be9a882540f1922577abba4c872ager@chromium.org#define __ ACCESS_MASM(masm)
405c838251403b0be9a882540f1922577abba4c872ager@chromium.org
415c838251403b0be9a882540f1922577abba4c872ager@chromium.org
42c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.orgstatic void ProbeTable(Isolate* isolate,
43c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                       MacroAssembler* masm,
44c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                       Code::Flags flags,
45c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                       StubCache::Table table,
4635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                       Register receiver,
47c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                       Register name,
4835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                       // Number of the cache entry, not scaled.
49c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                       Register offset,
50c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                       Register scratch,
5135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                       Register scratch2,
5235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                       Register offset_scratch) {
53c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
54c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
5535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ExternalReference map_offset(isolate->stub_cache()->map_reference(table));
56c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
57c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address());
58c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address());
5935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  uint32_t map_off_addr = reinterpret_cast<uint32_t>(map_offset.address());
60c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
61c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check the relative positions of the address fields.
62c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(value_off_addr > key_off_addr);
63c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT((value_off_addr - key_off_addr) % 4 == 0);
64c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT((value_off_addr - key_off_addr) < (256 * 4));
6535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ASSERT(map_off_addr > key_off_addr);
6635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ASSERT((map_off_addr - key_off_addr) % 4 == 0);
6735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ASSERT((map_off_addr - key_off_addr) < (256 * 4));
68c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
69c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss;
7035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  Register base_addr = scratch;
7135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  scratch = no_reg;
7235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org
7335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // Multiply by 3 because there are 3 fields per entry (name, code, map).
7435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ sll(offset_scratch, offset, 1);
7535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Addu(offset_scratch, offset_scratch, offset);
7635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org
7735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // Calculate the base address of the entry.
7835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ li(base_addr, Operand(key_offset));
7935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ sll(at, offset_scratch, kPointerSizeLog2);
8035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Addu(base_addr, base_addr, at);
81c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
82c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the key in the entry matches the name.
8335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ lw(at, MemOperand(base_addr, 0));
8435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Branch(&miss, ne, name, Operand(at));
8535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org
8635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // Check the map matches.
8735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ lw(at, MemOperand(base_addr, map_off_addr - key_off_addr));
8835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ lw(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset));
8935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Branch(&miss, ne, at, Operand(scratch2));
90c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
91c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the code entry from the cache.
9235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  Register code = scratch2;
9335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  scratch2 = no_reg;
9435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ lw(code, MemOperand(base_addr, value_off_addr - key_off_addr));
95c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
96c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the flags match what we're looking for.
9735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  Register flags_reg = base_addr;
9835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  base_addr = no_reg;
9935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ lw(flags_reg, FieldMemOperand(code, Code::kFlagsOffset));
10035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ And(flags_reg, flags_reg, Operand(~Code::kFlagsNotUsedInLookup));
10135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Branch(&miss, ne, flags_reg, Operand(flags));
10235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org
10335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org#ifdef DEBUG
10435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org    if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
10535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org      __ jmp(&miss);
10635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org    } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
10735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org      __ jmp(&miss);
10835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org    }
10935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org#endif
110c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
111c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Jump to the first instruction in the code stub.
11235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Addu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag));
11335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Jump(at);
114c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
115c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Miss: fall through.
116c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&miss);
117c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
118c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
119c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
120057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.orgvoid StubCompiler::GenerateDictionaryNegativeLookup(MacroAssembler* masm,
121057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Label* miss_label,
122057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Register receiver,
123057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Handle<Name> name,
124057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Register scratch0,
125057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                                    Register scratch1) {
1269faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  ASSERT(name->IsUniqueName());
127057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  ASSERT(!receiver.is(scratch0));
128394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Counters* counters = masm->isolate()->counters();
129394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
130394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
131394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
132394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Label done;
133394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
134394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  const int kInterceptorOrAccessCheckNeededMask =
135394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
136394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
137394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Bail out if the receiver has a named interceptor or requires access checks.
138394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Register map = scratch1;
139394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ lw(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
140394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
141394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ And(scratch0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
142394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ Branch(miss_label, ne, scratch0, Operand(zero_reg));
143394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
144394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Check that receiver is a JSObject.
145394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
146394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ Branch(miss_label, lt, scratch0, Operand(FIRST_SPEC_OBJECT_TYPE));
147394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
148394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Load properties array.
149394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Register properties = scratch0;
150394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
151394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Check that the properties array is a dictionary.
152394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset));
153394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Register tmp = properties;
154394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
155394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ Branch(miss_label, ne, map, Operand(tmp));
156394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
157394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Restore the temporarily used register.
158394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
159394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
160394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1619faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  NameDictionaryLookupStub::GenerateNegativeLookup(masm,
1629faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                   miss_label,
1639faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                   &done,
1649faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                   receiver,
1659faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                   properties,
1669faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                   name,
1679faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                   scratch1);
168394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ bind(&done);
169394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
170394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
171394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
172394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1735c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid StubCache::GenerateProbe(MacroAssembler* masm,
1745c838251403b0be9a882540f1922577abba4c872ager@chromium.org                              Code::Flags flags,
1755c838251403b0be9a882540f1922577abba4c872ager@chromium.org                              Register receiver,
1765c838251403b0be9a882540f1922577abba4c872ager@chromium.org                              Register name,
1775c838251403b0be9a882540f1922577abba4c872ager@chromium.org                              Register scratch,
178e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org                              Register extra,
17935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                              Register extra2,
18035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                              Register extra3) {
181c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Isolate* isolate = masm->isolate();
182c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss;
183c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
18435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // Make sure that code is valid. The multiplying code relies on the
18535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // entry size being 12.
18635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ASSERT(sizeof(Entry) == 12);
187c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
188c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Make sure the flags does not name a specific type.
189c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
190c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
191c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Make sure that there are no register conflicts.
192c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!scratch.is(receiver));
193c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!scratch.is(name));
194c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra.is(receiver));
195c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra.is(name));
196c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra.is(scratch));
197c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra2.is(receiver));
198c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra2.is(name));
199c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra2.is(scratch));
200c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra2.is(extra));
201c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
20235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // Check register validity.
203c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!scratch.is(no_reg));
204c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra.is(no_reg));
205c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!extra2.is(no_reg));
20635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ASSERT(!extra3.is(no_reg));
20735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org
20835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  Counters* counters = masm->isolate()->counters();
20935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1,
21035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                      extra2, extra3);
211c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
212c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the receiver isn't a smi.
21335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ JumpIfSmi(receiver, &miss);
214c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
215c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the map of the receiver and compute the hash.
2169faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  __ lw(scratch, FieldMemOperand(name, Name::kHashFieldOffset));
21735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ lw(at, FieldMemOperand(receiver, HeapObject::kMapOffset));
21835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Addu(scratch, scratch, at);
21935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  uint32_t mask = kPrimaryTableSize - 1;
22035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // We shift out the last two bits because they are not part of the hash and
22135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  // they are always 01 for maps.
22235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ srl(scratch, scratch, kHeapObjectTagSize);
22335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Xor(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask));
22435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ And(scratch, scratch, Operand(mask));
225c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
226c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Probe the primary table.
22735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ProbeTable(isolate,
22835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             masm,
22935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             flags,
23035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             kPrimary,
23135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             receiver,
23235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             name,
23335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             scratch,
23435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             extra,
23535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             extra2,
23635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             extra3);
237c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
238c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Primary miss: Compute hash for secondary probe.
23935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ srl(at, name, kHeapObjectTagSize);
24035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Subu(scratch, scratch, at);
24135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  uint32_t mask2 = kSecondaryTableSize - 1;
24235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ Addu(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask2));
24335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ And(scratch, scratch, Operand(mask2));
244c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
245c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Probe the secondary table.
24635814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  ProbeTable(isolate,
24735814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             masm,
24835814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             flags,
24935814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             kSecondary,
25035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             receiver,
25135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             name,
25235814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             scratch,
25335814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             extra,
25435814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             extra2,
25535814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org             extra3);
256c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
257c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Cache miss: Fall-through and let caller handle the miss by
258c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // entering the runtime system.
259c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&miss);
26035814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org  __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1,
26135814e51cffd39ade0aaeaaafb9b4612aa1d9efbfschneider@chromium.org                      extra2, extra3);
2625c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
2635c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2645c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2655c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
2665c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                                       int index,
2675c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                                       Register prototype) {
268c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load the global or builtins object from the current context.
269c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(prototype,
27046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org        MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
27146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the native context from the global or builtins object.
27246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ lw(prototype,
27346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org         FieldMemOperand(prototype, GlobalObject::kNativeContextOffset));
27446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the function from the native context.
275c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(prototype, MemOperand(prototype, Context::SlotOffset(index)));
276c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load the initial map.  The global functions all have initial maps.
277c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(prototype,
278c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org         FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
279c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load the prototype from the initial map.
280c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
2815c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
2825c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2835c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
285c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    MacroAssembler* masm,
286c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    int index,
287c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Register prototype,
288c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Label* miss) {
289c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Isolate* isolate = masm->isolate();
290c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check we're still in the same context.
29146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ lw(prototype,
29246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org        MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
293c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!prototype.is(at));
29446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ li(at, isolate->global_object());
295c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(miss, ne, prototype, Operand(at));
296c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the global function with the given index.
297c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Handle<JSFunction> function(
29846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      JSFunction::cast(isolate->native_context()->get(index)));
299c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load its initial map. The global functions all have initial maps.
300c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ li(prototype, Handle<Map>(function->initial_map()));
301c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load the prototype from the initial map.
302c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
3037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
3047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
30657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.orgvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
30757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            Register dst,
30857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            Register src,
30957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            bool inobject,
31057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            int index,
31157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                                            Representation representation) {
31257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  ASSERT(!FLAG_track_double_fields || !representation.IsDouble());
3139faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  int offset = index * kPointerSize;
3149faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  if (!inobject) {
3159faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    // Calculate the offset into the properties array.
3169faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    offset = offset + FixedArray::kHeaderSize;
3179faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
3189faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    src = dst;
319c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
3209faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  __ lw(dst, FieldMemOperand(src, offset));
3215c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
3225c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3235c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3245c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
3255c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                           Register receiver,
3265c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                           Register scratch,
3275c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                           Label* miss_label) {
328c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the receiver isn't a smi.
329c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ JumpIfSmi(receiver, miss_label);
330c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
331c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the object is a JS array.
332c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ GetObjectType(receiver, scratch, scratch);
333c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(miss_label, ne, scratch, Operand(JS_ARRAY_TYPE));
334c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
335c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load length directly from the JS array.
3368a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ Ret(USE_DELAY_SLOT);
337c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
338c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
339c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
340c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
341c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org// Generate code to check if an object is a string.  If the object is a
342c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org// heap object, its map's instance type is left in the scratch1 register.
343c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org// If this is not needed, scratch1 and scratch2 may be the same register.
344c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.orgstatic void GenerateStringCheck(MacroAssembler* masm,
345c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                Register receiver,
346c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                Register scratch1,
347c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                Register scratch2,
348c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                Label* smi,
349c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                Label* non_string_object) {
350c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the receiver isn't a smi.
351c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ JumpIfSmi(receiver, smi, t0);
352c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
353c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the object is a string.
354c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
355c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
356c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ And(scratch2, scratch1, Operand(kIsNotStringMask));
357c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // The cast is to resolve the overload for the argument of 0x0.
358c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(non_string_object,
359c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org            ne,
360c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org            scratch2,
361c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org            Operand(static_cast<int32_t>(kStringTag)));
3625c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
3635c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3645c838251403b0be9a882540f1922577abba4c872ager@chromium.org
3657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Generate code to load the length from a string object and return the length.
3667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// If the receiver object is not a string or a wrapped string object the
3677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// execution continues at the miss label. The register containing the
3687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// receiver is potentially clobbered.
3697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
3707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                            Register receiver,
3717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                            Register scratch1,
3727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                            Register scratch2,
373528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                            Label* miss) {
374c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label check_wrapper;
375c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
376c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check if the object is a string leaving the instance type in the
377c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // scratch1 register.
378528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  GenerateStringCheck(masm, receiver, scratch1, scratch2, miss, &check_wrapper);
379c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
380c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load length directly from the string.
3818a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ Ret(USE_DELAY_SLOT);
382c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(v0, FieldMemOperand(receiver, String::kLengthOffset));
383c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
384528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Check if the object is a JSValue wrapper.
385528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ bind(&check_wrapper);
386528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ Branch(miss, ne, scratch1, Operand(JS_VALUE_TYPE));
387c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
388528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Unwrap the value and check if the wrapped value is a string.
389528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ lw(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset));
390528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss);
391528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ Ret(USE_DELAY_SLOT);
392528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ lw(v0, FieldMemOperand(scratch1, String::kLengthOffset));
3937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
3947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3965c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
3975c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                                 Register receiver,
3985c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                                 Register scratch1,
3995c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                                 Register scratch2,
4005c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                                 Label* miss_label) {
401c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
4028a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ Ret(USE_DELAY_SLOT);
403c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ mov(v0, scratch1);
4045c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
4055c838251403b0be9a882540f1922577abba4c872ager@chromium.org
4065c838251403b0be9a882540f1922577abba4c872ager@chromium.org
407057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.orgvoid StubCompiler::GenerateCheckPropertyCell(MacroAssembler* masm,
408057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                             Handle<JSGlobalObject> global,
409057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                             Handle<Name> name,
410057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                             Register scratch,
411057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org                                             Label* miss) {
412057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
413e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(cell->value()->IsTheHole());
414e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ li(scratch, Operand(cell));
415f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org  __ lw(scratch, FieldMemOperand(scratch, Cell::kValueOffset));
416e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
417e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ Branch(miss, ne, scratch, Operand(at));
418e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
419e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
420e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
4212efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid StoreStubCompiler::GenerateNegativeHolderLookup(
422bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    MacroAssembler* masm,
423bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Handle<JSObject> holder,
424bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Register holder_reg,
425bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Handle<Name> name,
426bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Label* miss) {
427bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  if (holder->IsJSGlobalObject()) {
428bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    GenerateCheckPropertyCell(
429057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org        masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss);
430bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) {
431bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    GenerateDictionaryNegativeLookup(
432bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        masm, miss, holder_reg, name, scratch1(), scratch2());
433bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
434bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org}
435bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
436bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
437e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// Generate StoreTransition code, value is passed in a0 register.
4385c838251403b0be9a882540f1922577abba4c872ager@chromium.org// After executing generated code, the receiver_reg and name_reg
4395c838251403b0be9a882540f1922577abba4c872ager@chromium.org// may be clobbered.
4402efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
4412efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Handle<JSObject> object,
4422efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                LookupResult* lookup,
4432efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Handle<Map> transition,
4442efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Handle<Name> name,
4452efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register receiver_reg,
4462efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register storage_reg,
4472efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register value_reg,
4482efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register scratch1,
4492efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register scratch2,
4502efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Register scratch3,
4512efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Label* miss_label,
4522efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                                Label* slow) {
453c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // a0 : value.
454c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label exit;
4557028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
456f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  int descriptor = transition->LastAdded();
457f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  DescriptorArray* descriptors = transition->instance_descriptors();
458f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  PropertyDetails details = descriptors->GetDetails(descriptor);
459f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  Representation representation = details.representation();
460f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  ASSERT(!representation.IsNone());
461f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
462fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  if (details.type() == CONSTANT) {
463fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org    Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate());
464057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org    __ li(scratch1, constant);
465bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ Branch(miss_label, ne, value_reg, Operand(scratch1));
466b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  } else if (FLAG_track_fields && representation.IsSmi()) {
467bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ JumpIfNotSmi(value_reg, miss_label);
468906e2fb760f52fe6e75b744b1ea42576ea5b2c29ulan@chromium.org  } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
469bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ JumpIfSmi(value_reg, miss_label);
47057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  } else if (FLAG_track_double_fields && representation.IsDouble()) {
47157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    Label do_store, heap_number;
47257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex);
47357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow);
47457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
47557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ JumpIfNotSmi(value_reg, &heap_number);
47657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ SmiUntag(scratch1, value_reg);
47757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ mtc1(scratch1, f6);
47857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ cvt_d_w(f4, f6);
47957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ jmp(&do_store);
48057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
48157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ bind(&heap_number);
48257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex,
483bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                miss_label, DONT_DO_SMI_CHECK);
48457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
48557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
48657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ bind(&do_store);
48757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset));
48857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  }
48957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
490c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Stub never generated for non-global objects that require access
491c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // checks.
492c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
493c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
494c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Perform map transition for the receiver if necessary.
495b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  if (details.type() == FIELD &&
496b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org      object->map()->unused_property_fields() == 0) {
497c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // The properties must be extended before we can store the value.
498c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // We jump to a runtime call that extends the properties array.
499c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ push(receiver_reg);
5006e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    __ li(a2, Operand(transition));
501c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Push(a2, a0);
502c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ TailCallExternalReference(
503c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org           ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
504c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                             masm->isolate()),
505c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org           3, 1);
506c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return;
507c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
508c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
509e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Update the map of the object.
510e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ li(scratch1, Operand(transition));
511e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ sw(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
512e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
513bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // Update the write barrier for the map field.
514e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ RecordWriteField(receiver_reg,
515e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      HeapObject::kMapOffset,
516e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      scratch1,
51757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      scratch2,
518e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      kRAHasNotBeenSaved,
519e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      kDontSaveFPRegs,
520e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      OMIT_REMEMBERED_SET,
521e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                      OMIT_SMI_CHECK);
522e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
523fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  if (details.type() == CONSTANT) {
524b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    ASSERT(value_reg.is(a0));
525b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    __ Ret(USE_DELAY_SLOT);
526b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    __ mov(v0, a0);
527b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    return;
528b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  }
529b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
530e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  int index = transition->instance_descriptors()->GetFieldIndex(
531e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      transition->LastAdded());
532e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
533e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Adjust for the number of properties stored in the object. Even in the
534e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // face of a transition we can use the old map here because the size of the
535e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // object and the number of in-object properties is not going to change.
536e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  index -= object->map()->inobject_properties();
537e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
538e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // TODO(verwaest): Share this code as a code stub.
539a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  SmiCheck smi_check = representation.IsTagged()
540a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
541e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (index < 0) {
542e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Set the property straight into the object.
543e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    int offset = object->map()->instance_size() + (index * kPointerSize);
54457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    if (FLAG_track_double_fields && representation.IsDouble()) {
54557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ sw(storage_reg, FieldMemOperand(receiver_reg, offset));
54657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    } else {
54757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ sw(value_reg, FieldMemOperand(receiver_reg, offset));
54857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    }
549e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
550f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    if (!FLAG_track_fields || !representation.IsSmi()) {
551f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Update the write barrier for the array address.
55257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      if (!FLAG_track_double_fields || !representation.IsDouble()) {
553bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        __ mov(storage_reg, value_reg);
55457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      }
555f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ RecordWriteField(receiver_reg,
556f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          offset,
557bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                          storage_reg,
558f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          scratch1,
559f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          kRAHasNotBeenSaved,
560a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          kDontSaveFPRegs,
561a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          EMIT_REMEMBERED_SET,
562a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          smi_check);
563f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
564f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  } else {
565e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Write to the properties array.
566e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    int offset = index * kPointerSize + FixedArray::kHeaderSize;
567e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Get the properties array
568e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ lw(scratch1,
569e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org          FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
57057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    if (FLAG_track_double_fields && representation.IsDouble()) {
57157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ sw(storage_reg, FieldMemOperand(scratch1, offset));
57257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    } else {
57357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ sw(value_reg, FieldMemOperand(scratch1, offset));
57457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    }
575e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
576f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    if (!FLAG_track_fields || !representation.IsSmi()) {
577f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Update the write barrier for the array address.
57857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      if (!FLAG_track_double_fields || !representation.IsDouble()) {
579bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        __ mov(storage_reg, value_reg);
58057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      }
581f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ RecordWriteField(scratch1,
582f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          offset,
583bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                          storage_reg,
584f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          receiver_reg,
585f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          kRAHasNotBeenSaved,
586a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          kDontSaveFPRegs,
587a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          EMIT_REMEMBERED_SET,
588a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          smi_check);
589f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
590e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
591e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
592e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Return the value (register v0).
593e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(value_reg.is(a0));
594e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ bind(&exit);
5958a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ Ret(USE_DELAY_SLOT);
596e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(v0, a0);
597e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
598e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
599e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
600e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// Generate StoreField code, value is passed in a0 register.
601e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// When leaving generated code after success, the receiver_reg and name_reg
602e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// may be clobbered.  Upon branch to miss_label, the receiver and name
603e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// registers have their original values.
6042efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
6052efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Handle<JSObject> object,
6062efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           LookupResult* lookup,
6072efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register receiver_reg,
6082efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register name_reg,
6092efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register value_reg,
6102efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register scratch1,
6112efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Register scratch2,
6122efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                           Label* miss_label) {
613e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // a0 : value
614e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Label exit;
615e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
616e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Stub never generated for non-global objects that require access
617e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // checks.
618e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
619e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
620e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  int index = lookup->GetFieldIndex().field_index();
621e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
622c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Adjust for the number of properties stored in the object. Even in the
623c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // face of a transition we can use the old map here because the size of the
624c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // object and the number of in-object properties is not going to change.
625c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  index -= object->map()->inobject_properties();
626c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
627f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  Representation representation = lookup->representation();
628f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  ASSERT(!representation.IsNone());
629f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  if (FLAG_track_fields && representation.IsSmi()) {
630f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    __ JumpIfNotSmi(value_reg, miss_label);
631906e2fb760f52fe6e75b744b1ea42576ea5b2c29ulan@chromium.org  } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
632906e2fb760f52fe6e75b744b1ea42576ea5b2c29ulan@chromium.org    __ JumpIfSmi(value_reg, miss_label);
633f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  } else if (FLAG_track_double_fields && representation.IsDouble()) {
63457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    // Load the double storage.
63557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    if (index < 0) {
63657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      int offset = object->map()->instance_size() + (index * kPointerSize);
63757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ lw(scratch1, FieldMemOperand(receiver_reg, offset));
63857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    } else {
63957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ lw(scratch1,
64057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org            FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
64157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      int offset = index * kPointerSize + FixedArray::kHeaderSize;
64257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      __ lw(scratch1, FieldMemOperand(scratch1, offset));
64357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    }
64457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
64557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    // Store the value into the storage.
64657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    Label do_store, heap_number;
64757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ JumpIfNotSmi(value_reg, &heap_number);
64857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ SmiUntag(scratch2, value_reg);
64957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ mtc1(scratch2, f6);
65057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ cvt_d_w(f4, f6);
65157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ jmp(&do_store);
65257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
65357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ bind(&heap_number);
65457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex,
655f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                miss_label, DONT_DO_SMI_CHECK);
65657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
65757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
658f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    __ bind(&do_store);
65957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ sdc1(f4, FieldMemOperand(scratch1, HeapNumber::kValueOffset));
66057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    // Return the value (register v0).
66157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    ASSERT(value_reg.is(a0));
6628a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org    __ Ret(USE_DELAY_SLOT);
66357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    __ mov(v0, a0);
66457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    return;
665f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  }
666f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
667e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // TODO(verwaest): Share this code as a code stub.
668a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  SmiCheck smi_check = representation.IsTagged()
669a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
670c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (index < 0) {
671c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Set the property straight into the object.
672c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    int offset = object->map()->instance_size() + (index * kPointerSize);
6732bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    __ sw(value_reg, FieldMemOperand(receiver_reg, offset));
674c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
675f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    if (!FLAG_track_fields || !representation.IsSmi()) {
676f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Skip updating write barrier if storing a smi.
677f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ JumpIfSmi(value_reg, &exit);
678f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
679f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Update the write barrier for the array address.
680f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Pass the now unused name_reg as a scratch register.
681f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ mov(name_reg, value_reg);
682f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ RecordWriteField(receiver_reg,
683f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          offset,
684f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          name_reg,
685f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          scratch1,
686f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          kRAHasNotBeenSaved,
687a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          kDontSaveFPRegs,
688a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          EMIT_REMEMBERED_SET,
689a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          smi_check);
690f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
691c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
692c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Write to the properties array.
693c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    int offset = index * kPointerSize + FixedArray::kHeaderSize;
694c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Get the properties array.
6957028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ lw(scratch1,
6967028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
6972bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    __ sw(value_reg, FieldMemOperand(scratch1, offset));
698c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
699f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    if (!FLAG_track_fields || !representation.IsSmi()) {
700f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Skip updating write barrier if storing a smi.
701f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ JumpIfSmi(value_reg, &exit);
702f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org
703f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Update the write barrier for the array address.
704f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      // Ok to clobber receiver_reg and name_reg, since we return.
705f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ mov(name_reg, value_reg);
706f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ RecordWriteField(scratch1,
707f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          offset,
708f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          name_reg,
709f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          receiver_reg,
710f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org                          kRAHasNotBeenSaved,
711a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          kDontSaveFPRegs,
712a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          EMIT_REMEMBERED_SET,
713a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org                          smi_check);
714f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
715c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
716c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
717c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the value (register v0).
7182bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  ASSERT(value_reg.is(a0));
719c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&exit);
7208a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ Ret(USE_DELAY_SLOT);
721c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ mov(v0, a0);
7225c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
7235c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7245c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7252efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
7262efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                            Label* label,
7272efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                            Handle<Name> name) {
7282bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  if (!label->is_unused()) {
7292bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    __ bind(label);
7302bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    __ li(this->name(), Operand(name));
7312bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  }
732068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org}
733068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org
734068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org
735c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.orgstatic void PushInterceptorArguments(MacroAssembler* masm,
736c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                     Register receiver,
737c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                     Register holder,
738c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                     Register name,
739c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                     Handle<JSObject> holder_obj) {
7404a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0);
7414a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1);
7424a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2);
7434a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3);
7444a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4);
745c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ push(name);
746c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
747c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor));
748c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Register scratch = name;
749c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ li(scratch, Operand(interceptor));
750c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Push(scratch, receiver, holder);
751c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
752c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
753c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
754c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgstatic void CompileCallLoadPropertyWithInterceptor(
755c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    MacroAssembler* masm,
756c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Register receiver,
757c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Register holder,
758c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Register name,
75937be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org    Handle<JSObject> holder_obj,
76037be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org    IC::UtilityId id) {
761c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
76237be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org  __ CallExternalReference(
76337be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      ExternalReference(IC_Utility(id), masm->isolate()),
76437be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      StubCache::kInterceptorArgsLength);
765c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
766c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
767c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
768bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.orgstatic const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
769c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
770ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com// Reserves space for the extra arguments to API function in the
771c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org// caller's frame.
772c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org//
773c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org// These arguments are set by CheckPrototypes and GenerateFastApiDirectCall.
774c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.orgstatic void ReserveSpaceForFastApiCall(MacroAssembler* masm,
775c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                       Register scratch) {
776c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(Smi::FromInt(0) == 0);
777c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  for (int i = 0; i < kFastApiCallArguments; i++) {
778c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ push(zero_reg);
779c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
780c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
781c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
782c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
783c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org// Undoes the effects of ReserveSpaceForFastApiCall.
784c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.orgstatic void FreeSpaceForFastApiCall(MacroAssembler* masm) {
785c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Drop(kFastApiCallArguments);
7865c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
7875c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7885c838251403b0be9a882540f1922577abba4c872ager@chromium.org
789c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgstatic void GenerateFastApiDirectCall(MacroAssembler* masm,
790c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                      const CallOptimization& optimization,
791528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                      int argc,
792528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                      bool restore_context) {
793c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // ----------- S t a t e -------------
794cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org  //  -- sp[0] - sp[24]     : FunctionCallbackInfo, incl.
795cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org  //                        :  holder (set by CheckPrototypes)
796528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  //  -- sp[28]             : last JS argument
797c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  //  -- ...
798528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  //  -- sp[(argc + 6) * 4] : first JS argument
799528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  //  -- sp[(argc + 7) * 4] : receiver
800c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // -----------------------------------
801cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org  typedef FunctionCallbackArguments FCA;
802528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Save calling context.
803fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ sw(cp, MemOperand(sp, FCA::kContextSaveIndex * kPointerSize));
804c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the function and setup the context.
805c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Handle<JSFunction> function = optimization.constant_function();
806057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  __ li(t1, function);
807c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(cp, FieldMemOperand(t1, JSFunction::kContextOffset));
808fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ sw(t1, MemOperand(sp, FCA::kCalleeIndex * kPointerSize));
809c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
810cfdf67d672b8e2cd6cc1df14c082671511745746machenbach@chromium.org  // Construct the FunctionCallbackInfo.
811c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
81209d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org  Handle<Object> call_data(api_call_info->data(), masm->isolate());
813c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (masm->isolate()->heap()->InNewSpace(*call_data)) {
814c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    __ li(a0, api_call_info);
815c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lw(t2, FieldMemOperand(a0, CallHandlerInfo::kDataOffset));
816c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
817c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    __ li(t2, call_data);
818c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
819528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Store call data.
820fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ sw(t2, MemOperand(sp, FCA::kDataIndex * kPointerSize));
821528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Store isolate.
82232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  __ li(t3, Operand(ExternalReference::isolate_address(masm->isolate())));
823fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ sw(t3, MemOperand(sp, FCA::kIsolateIndex * kPointerSize));
824528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // Store ReturnValue default and ReturnValue.
825bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ LoadRoot(t1, Heap::kUndefinedValueRootIndex);
826fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ sw(t1, MemOperand(sp, FCA::kReturnValueOffset * kPointerSize));
827fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ sw(t1, MemOperand(sp, FCA::kReturnValueDefaultValueIndex * kPointerSize));
828c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
829ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Prepare arguments.
830fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ Move(a2, sp);
831c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
832ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Allocate the v8::Arguments structure in the arguments' space since
833ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // it's not controlled by GC.
834c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  const int kApiStackSpace = 4;
835c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
836c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  FrameScope frame_scope(masm, StackFrame::MANUAL);
837c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ EnterExitFrame(false, kApiStackSpace);
838c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
839fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  // a0 = FunctionCallbackInfo&
840c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Arguments is built at sp + 1 (sp is a reserved spot for ra).
841662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ Addu(a0, sp, kPointerSize);
842fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  // FunctionCallbackInfo::implicit_args_
843662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ sw(a2, MemOperand(a0, 0 * kPointerSize));
844fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  // FunctionCallbackInfo::values_
845fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ Addu(t0, a2, Operand((kFastApiCallArguments - 1 + argc) * kPointerSize));
846662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ sw(t0, MemOperand(a0, 1 * kPointerSize));
847fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  // FunctionCallbackInfo::length_ = argc
848c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ li(t0, Operand(argc));
849662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ sw(t0, MemOperand(a0, 2 * kPointerSize));
850fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  // FunctionCallbackInfo::is_construct_call = 0
851662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ sw(zero_reg, MemOperand(a0, 3 * kPointerSize));
852c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
853fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  const int kStackUnwindSpace = argc + kFastApiCallArguments + 1;
854662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  Address function_address = v8::ToCData<Address>(api_call_info->callback());
855c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ApiFunction fun(function_address);
856662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
857c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ExternalReference ref =
858c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      ExternalReference(&fun,
859bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org                        type,
860c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                        masm->isolate());
861662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
862662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL;
863b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  ApiFunction thunk_fun(thunk_address);
864b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type,
865b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org      masm->isolate());
866b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
867c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  AllowExternalCallThatCantCauseGC scope(masm);
868528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  MemOperand context_restore_operand(
869fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org      fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
870528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  MemOperand return_value_operand(
871fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org      fp, (2 + FCA::kReturnValueOffset) * kPointerSize);
872fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org
873bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ CallApiFunctionAndReturn(ref,
874b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org                              function_address,
875b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org                              thunk_ref,
876662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org                              a1,
877bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org                              kStackUnwindSpace,
878528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                              return_value_operand,
879528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                              restore_context ?
880528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                  &context_restore_operand : NULL);
881c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
882c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
883639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
884639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org// Generate call to api function.
885639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.orgstatic void GenerateFastApiCall(MacroAssembler* masm,
886639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org                                const CallOptimization& optimization,
887639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org                                Register receiver,
888639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org                                Register scratch,
889639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org                                int argc,
890639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org                                Register* values) {
891639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  ASSERT(optimization.is_simple_api_call());
892639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  ASSERT(!receiver.is(scratch));
893639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
894fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  typedef FunctionCallbackArguments FCA;
895639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  const int stack_space = kFastApiCallArguments + argc + 1;
896639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  // Assign stack space for the call arguments.
897639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  __ Subu(sp, sp, Operand(stack_space * kPointerSize));
898639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  // Write holder to stack frame.
899fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ sw(receiver, MemOperand(sp, FCA::kHolderIndex * kPointerSize));
900639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  // Write receiver to stack frame.
901639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  int index = stack_space - 1;
902639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  __ sw(receiver, MemOperand(sp, index * kPointerSize));
903639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  // Write the arguments to stack frame.
904639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  for (int i = 0; i < argc; i++) {
905639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    ASSERT(!receiver.is(values[i]));
906639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    ASSERT(!scratch.is(values[i]));
907639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    __ sw(receiver, MemOperand(sp, index-- * kPointerSize));
908639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  }
909639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
910528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  GenerateFastApiDirectCall(masm, optimization, argc, true);
911639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org}
912639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
913639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
9147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgclass CallInterceptorCompiler BASE_EMBEDDED {
9157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org public:
9168a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  CallInterceptorCompiler(CallStubCompiler* stub_compiler,
9177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                          const ParameterCount& arguments,
918d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com                          Register name,
919cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org                          ExtraICState extra_ic_state)
9207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      : stub_compiler_(stub_compiler),
9217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org        arguments_(arguments),
922d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com        name_(name),
923d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com        extra_ic_state_(extra_ic_state) {}
9247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
925c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  void Compile(MacroAssembler* masm,
926c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Handle<JSObject> object,
927c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Handle<JSObject> holder,
9289faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org               Handle<Name> name,
929c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               LookupResult* lookup,
930c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Register receiver,
931c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Register scratch1,
932c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Register scratch2,
933c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Register scratch3,
934c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org               Label* miss) {
935c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    ASSERT(holder->HasNamedInterceptor());
936c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
937c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
938c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Check that the receiver isn't a smi.
939c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ JumpIfSmi(receiver, miss);
940c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    CallOptimization optimization(lookup);
941c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (optimization.is_constant_call()) {
942c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
943c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                       holder, lookup, name, optimization, miss);
944c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    } else {
945c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
946c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                     name, holder, miss);
947c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
948c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
949c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
950c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org private:
951c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  void CompileCacheable(MacroAssembler* masm,
952c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Handle<JSObject> object,
953c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Register receiver,
954c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Register scratch1,
955c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Register scratch2,
956c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Register scratch3,
957c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Handle<JSObject> interceptor_holder,
958c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        LookupResult* lookup,
9599faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                        Handle<Name> name,
960c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        const CallOptimization& optimization,
961c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        Label* miss_label) {
962c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    ASSERT(optimization.is_constant_call());
963c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    ASSERT(!lookup->holder()->IsGlobalObject());
964c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Counters* counters = masm->isolate()->counters();
965c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    int depth1 = kInvalidProtoDepth;
966c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    int depth2 = kInvalidProtoDepth;
967c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    bool can_do_fast_api_call = false;
968c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (optimization.is_simple_api_call() &&
969c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          !lookup->holder()->IsGlobalObject()) {
970c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      depth1 = optimization.GetPrototypeDepthOfExpectedType(
971c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          object, interceptor_holder);
972c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      if (depth1 == kInvalidProtoDepth) {
973c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        depth2 = optimization.GetPrototypeDepthOfExpectedType(
974c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org            interceptor_holder, Handle<JSObject>(lookup->holder()));
975c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      }
976c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      can_do_fast_api_call =
977c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
978c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
979c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
980c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ IncrementCounter(counters->call_const_interceptor(), 1,
981c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        scratch1, scratch2);
982c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
983c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (can_do_fast_api_call) {
984c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1,
985c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                          scratch1, scratch2);
986c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      ReserveSpaceForFastApiCall(masm, scratch1);
987c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
988c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
989c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Check that the maps from receiver to interceptor's holder
990c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // haven't changed and thus we can invoke interceptor.
991c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Label miss_cleanup;
992c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
993c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Register holder =
994f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        stub_compiler_->CheckPrototypes(
995f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            IC::CurrentTypeOf(object, masm->isolate()), receiver,
996f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            interceptor_holder, scratch1, scratch2, scratch3,
997f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            name, depth1, miss);
998c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
999c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Invoke an interceptor and if it provides a value,
1000c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // branch to |regular_invoke|.
1001c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Label regular_invoke;
1002c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2,
1003c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                        &regular_invoke);
1004c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1005c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Interceptor returned nothing for this property.  Try to use cached
1006c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // constant function.
1007c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1008c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Check that the maps from interceptor's holder to constant function's
1009c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // holder haven't changed and thus we can use cached constant function.
1010c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    if (*interceptor_holder != lookup->holder()) {
1011f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      stub_compiler_->CheckPrototypes(
1012089ff3201a058d730ea38791253f36b2fc534ae2palfia@homejinni.com          IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
1013f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org          handle(lookup->holder()), scratch1, scratch2, scratch3,
1014f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org          name, depth2, miss);
1015c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    } else {
1016c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // CheckPrototypes has a side effect of fetching a 'holder'
1017c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // for API (object which is instanceof for the signature).  It's
1018c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // safe to omit it here, as if present, it should be fetched
1019c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // by the previous CheckPrototypes.
1020c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      ASSERT(depth2 == kInvalidProtoDepth);
1021c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
1022c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1023c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Invoke function.
1024c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (can_do_fast_api_call) {
1025528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org      GenerateFastApiDirectCall(
1026528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org          masm, optimization, arguments_.immediate(), false);
1027c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    } else {
102832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      Handle<JSFunction> function = optimization.constant_function();
1029089ff3201a058d730ea38791253f36b2fc534ae2palfia@homejinni.com      __ Move(a0, receiver);
1030089ff3201a058d730ea38791253f36b2fc534ae2palfia@homejinni.com      stub_compiler_->GenerateJumpFunction(object, function);
1031c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
1032c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1033c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Deferred code for fast API call case---clean preallocated space.
1034c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (can_do_fast_api_call) {
1035c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ bind(&miss_cleanup);
1036c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      FreeSpaceForFastApiCall(masm);
1037c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ Branch(miss_label);
1038c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
1039c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1040c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Invoke a regular function.
1041c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind(&regular_invoke);
1042c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (can_do_fast_api_call) {
1043c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      FreeSpaceForFastApiCall(masm);
1044c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
10457516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
10467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void CompileRegular(MacroAssembler* masm,
1048c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                      Handle<JSObject> object,
10497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                      Register receiver,
10507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                      Register scratch1,
10517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                      Register scratch2,
10527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                      Register scratch3,
10536e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org                      Handle<Name> name,
1054c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                      Handle<JSObject> interceptor_holder,
10557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                      Label* miss_label) {
1056c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Register holder =
1057f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        stub_compiler_->CheckPrototypes(
1058f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            IC::CurrentTypeOf(object, masm->isolate()), receiver,
1059f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            interceptor_holder, scratch1, scratch2, scratch3, name, miss_label);
1060c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1061c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Call a runtime function to load the interceptor property.
1062c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::INTERNAL);
1063c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Save the name_ register across the call.
1064c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ push(name_);
1065c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
106637be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org    CompileCallLoadPropertyWithInterceptor(
106737be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org        masm, receiver, holder, name_, interceptor_holder,
106837be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org        IC::kLoadPropertyWithInterceptorForCall);
1069c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1070c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Restore the name_ register.
1071c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ pop(name_);
1072c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Leave the internal frame.
10737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
10747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  void LoadWithInterceptor(MacroAssembler* masm,
10767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                           Register receiver,
10777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                           Register holder,
1078c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                           Handle<JSObject> holder_obj,
10797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                           Register scratch,
10807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                           Label* interceptor_succeeded) {
1081c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
1082c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FrameScope scope(masm, StackFrame::INTERNAL);
1083c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1084089ff3201a058d730ea38791253f36b2fc534ae2palfia@homejinni.com      __ Push(receiver, holder, name_);
108537be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      CompileCallLoadPropertyWithInterceptor(
108637be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org          masm, receiver, holder, name_, holder_obj,
108737be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org          IC::kLoadPropertyWithInterceptorOnly);
1088089ff3201a058d730ea38791253f36b2fc534ae2palfia@homejinni.com      __ pop(name_);
1089089ff3201a058d730ea38791253f36b2fc534ae2palfia@homejinni.com      __ pop(holder);
1090089ff3201a058d730ea38791253f36b2fc534ae2palfia@homejinni.com      __ pop(receiver);
1091c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
1092c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // If interceptor returns no-result sentinel, call the constant function.
1093c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
1094c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Branch(interceptor_succeeded, ne, v0, Operand(scratch));
10957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
10967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10978a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  CallStubCompiler* stub_compiler_;
10987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  const ParameterCount& arguments_;
10997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Register name_;
1100cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  ExtraICState extra_ic_state_;
11017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org};
11027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
11037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
11042bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.orgvoid StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
11059faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  __ Jump(code, RelocInfo::CODE_TARGET);
11069faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org}
11079faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org
11089faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org
11092bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org#undef __
11102bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org#define __ ACCESS_MASM(masm())
11112bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
11122bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
1113f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgRegister StubCompiler::CheckPrototypes(Handle<Type> type,
1114394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Register object_reg,
1115394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Handle<JSObject> holder,
1116394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Register holder_reg,
1117394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Register scratch1,
1118394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       Register scratch2,
11199faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                       Handle<Name> name,
1120394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       int save_at_depth,
11219faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                       Label* miss,
11229faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                       PrototypeCheckType check) {
1123f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
1124ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Make sure that the type feedback oracle harvests the receiver map.
1125ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // TODO(svenpanne) Remove this hack when all ICs are reworked.
1126f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  __ li(scratch1, Operand(receiver_map));
1127ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
1128394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Make sure there's no overlap between holder and object registers.
1129394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
1130394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1131394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com         && !scratch2.is(scratch1));
1132394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1133394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Keep track of the current object in register reg.
1134394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Register reg = object_reg;
1135394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  int depth = 0;
1136394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1137fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  typedef FunctionCallbackArguments FCA;
1138394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  if (save_at_depth == depth) {
1139fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org    __ sw(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize));
1140394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
1141394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1142f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<JSObject> current = Handle<JSObject>::null();
1143f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
1144f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<JSObject> prototype = Handle<JSObject>::null();
1145f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<Map> current_map = receiver_map;
1146f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Handle<Map> holder_map(holder->map());
1147f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  // Traverse the prototype chain and check the maps in the prototype chain for
1148f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  // fast and global objects or do negative lookup for normal objects.
1149f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  while (!current_map.is_identical_to(holder_map)) {
1150394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    ++depth;
1151394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1152394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Only global objects and objects that do not require access
1153394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // checks are allowed in stubs.
1154f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    ASSERT(current_map->IsJSGlobalProxyMap() ||
1155f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org           !current_map->is_access_check_needed());
1156394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1157f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    prototype = handle(JSObject::cast(current_map->prototype()));
1158f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    if (current_map->is_dictionary_map() &&
1159f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        !current_map->IsJSGlobalObjectMap() &&
1160f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        !current_map->IsJSGlobalProxyMap()) {
11619faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      if (!name->IsUniqueName()) {
11629faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        ASSERT(name->IsString());
11639faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        name = factory()->InternalizeString(Handle<String>::cast(name));
1164394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      }
1165f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      ASSERT(current.is_null() ||
1166f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org             current->property_dictionary()->FindEntry(*name) ==
11679faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org             NameDictionary::kNotFound);
1168394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1169394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
1170394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                       scratch1, scratch2);
1171394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1172394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
1173394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      reg = holder_reg;  // From now on the object will be in holder_reg.
1174394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
1175394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    } else {
11769faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      Register map_reg = scratch1;
1177f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      if (depth != 1 || check == CHECK_ALL_MAPS) {
11789faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        // CheckMap implicitly loads the map of |reg| into |map_reg|.
1179a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org        __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK);
11809faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      } else {
11819faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
11829faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      }
1183f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org
1184394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      // Check access rights to the global object.  This has to happen after
1185394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      // the map check so that we know that the object is actually a global
1186394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      // object.
1187f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      if (current_map->IsJSGlobalProxyMap()) {
1188394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        __ CheckAccessGlobalProxy(reg, scratch2, miss);
1189f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      } else if (current_map->IsJSGlobalObjectMap()) {
1190f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        GenerateCheckPropertyCell(
1191f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            masm(), Handle<JSGlobalObject>::cast(current), name,
1192f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org            scratch2, miss);
1193394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      }
1194f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org
1195394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      reg = holder_reg;  // From now on the object will be in holder_reg.
1196394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1197394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      if (heap()->InNewSpace(*prototype)) {
1198394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // The prototype is in new space; we cannot store a reference to it
1199394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // in the code.  Load it from the map.
12009faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        __ lw(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
1201394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      } else {
1202394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // The prototype is in old space; load it directly.
1203394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        __ li(reg, Operand(prototype));
1204394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      }
1205394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    }
1206394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1207394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    if (save_at_depth == depth) {
1208fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org      __ sw(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize));
1209394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    }
1210394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1211394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Go to the next object in the prototype chain.
1212394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    current = prototype;
1213f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    current_map = handle(current->map());
1214394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
1215394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1216394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Log the check depth.
121732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1218394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1219f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  if (depth != 0 || check == CHECK_ALL_MAPS) {
12209faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    // Check the holder map.
1221f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK);
12229faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  }
1223394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1224394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Perform security check for access to the global object.
1225f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  ASSERT(current_map->IsJSGlobalProxyMap() ||
1226f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org         !current_map->is_access_check_needed());
1227f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  if (current_map->IsJSGlobalProxyMap()) {
1228394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ CheckAccessGlobalProxy(reg, scratch1, miss);
1229394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
1230394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1231394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Return the register containing the holder.
1232394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  return reg;
1233394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
1234394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1235394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1236b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.orgvoid LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
12379faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  if (!miss->is_unused()) {
1238b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    Label success;
1239b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    __ Branch(&success);
12409faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    __ bind(miss);
12412bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org    TailCallBuiltin(masm(), MissBuiltin(kind()));
1242b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    __ bind(&success);
12439faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  }
12445c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12455c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12465c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1247b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.orgvoid StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
1248bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  if (!miss->is_unused()) {
1249b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    Label success;
1250b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    __ Branch(&success);
1251bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    GenerateRestoreName(masm(), miss, name);
1252bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    TailCallBuiltin(masm(), MissBuiltin(kind()));
1253b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    __ bind(&success);
1254bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
1255bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org}
1256bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
1257bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
12582efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgRegister LoadStubCompiler::CallbackHandlerFrontend(
1259f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    Handle<Type> type,
12604a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Register object_reg,
12614a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Handle<JSObject> holder,
12629faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Handle<Name> name,
12632c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org    Handle<Object> callback) {
12644a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Label miss;
1265c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1266f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss);
12675c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12684a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
12694a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    ASSERT(!reg.is(scratch2()));
12704a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    ASSERT(!reg.is(scratch3()));
12714a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    ASSERT(!reg.is(scratch4()));
12724a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
12734a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // Load the properties dictionary.
12744a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Register dictionary = scratch4();
12754a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ lw(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset));
12764a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
12774a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // Probe the dictionary.
12784a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Label probe_done;
12799faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    NameDictionaryLookupStub::GeneratePositiveLookup(masm(),
12809faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                     &miss,
12819faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                     &probe_done,
12829faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                     dictionary,
12839faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                     this->name(),
12849faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                     scratch2(),
12859faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                     scratch3());
12864a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ bind(&probe_done);
12874a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
12884a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // If probing finds an entry in the dictionary, scratch3 contains the
12894a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // pointer into the dictionary. Check that the value is the callback.
12904a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Register pointer = scratch3();
12919faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    const int kElementsStartOffset = NameDictionary::kHeaderSize +
12929faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        NameDictionary::kElementsStartIndex * kPointerSize;
12934a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    const int kValueOffset = kElementsStartOffset + kPointerSize;
12944a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ lw(scratch2(), FieldMemOperand(pointer, kValueOffset));
12954a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ Branch(&miss, ne, scratch2(), Operand(callback));
12964a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  }
12975c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1298b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  HandlerFrontendFooter(name, &miss);
12994a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  return reg;
1300471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org}
1301471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org
1302471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org
13032efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadField(Register reg,
13042efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                         Handle<JSObject> holder,
13052efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                         PropertyIndex field,
13062efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                         Representation representation) {
130757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  if (!reg.is(receiver())) __ mov(receiver(), reg);
130857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  if (kind() == Code::LOAD_IC) {
130957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    LoadFieldStub stub(field.is_inobject(holder),
131057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                       field.translate(holder),
131157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                       representation);
131257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    GenerateTailCall(masm(), stub.GetCode(isolate()));
131357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  } else {
131457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    KeyedLoadFieldStub stub(field.is_inobject(holder),
131557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                            field.translate(holder),
131657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                            representation);
131757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    GenerateTailCall(masm(), stub.GetCode(isolate()));
131857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  }
13194a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
13204a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
13214a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
13222efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
13234a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Return the constant value.
1324057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  __ li(v0, value);
13254a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ Ret();
13264a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
13274a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
13284a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
13292efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadCallback(
13302c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org    const CallOptimization& call_optimization) {
1331639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  GenerateFastApiCall(
1332639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org      masm(), call_optimization, receiver(), scratch3(), 0, NULL);
13332c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org}
13342c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org
13352c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org
13362efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadCallback(
13374a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Register reg,
13384a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Handle<ExecutableAccessorInfo> callback) {
1339c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Build AccessorInfo::args_ list on the stack and push property name below
1340c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // the exit frame to make GC aware of them and store pointers to them.
1341fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0);
1342fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1);
1343fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2);
1344fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3);
1345fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4);
1346fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5);
1347fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6);
13484a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  ASSERT(!scratch2().is(reg));
13494a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  ASSERT(!scratch3().is(reg));
13504a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  ASSERT(!scratch4().is(reg));
13514a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ push(receiver());
1352c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (heap()->InNewSpace(callback->data())) {
13534a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ li(scratch3(), callback);
13544a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ lw(scratch3(), FieldMemOperand(scratch3(),
13554a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                                      ExecutableAccessorInfo::kDataOffset));
1356c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
135732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    __ li(scratch3(), Handle<Object>(callback->data(), isolate()));
1358c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
135979d0bf7c99ebe30751b199f72fa06fe34a5ded48palfia@homejinni.com  __ Subu(sp, sp, 6 * kPointerSize);
13604a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ sw(scratch3(), MemOperand(sp, 5 * kPointerSize));
1361c118402c43ae44cf9255d36608a44886c98537c5jkummerow@chromium.org  __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex);
13624a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ sw(scratch3(), MemOperand(sp, 4 * kPointerSize));
136379d0bf7c99ebe30751b199f72fa06fe34a5ded48palfia@homejinni.com  __ sw(scratch3(), MemOperand(sp, 3 * kPointerSize));
1364c118402c43ae44cf9255d36608a44886c98537c5jkummerow@chromium.org  __ li(scratch4(),
136532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        Operand(ExternalReference::isolate_address(isolate())));
13664a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ sw(scratch4(), MemOperand(sp, 2 * kPointerSize));
13674a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ sw(reg, MemOperand(sp, 1 * kPointerSize));
13684a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ sw(name(), MemOperand(sp, 0 * kPointerSize));
1369fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  __ Addu(scratch2(), sp, 1 * kPointerSize);
1370ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
13714a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ mov(a2, scratch2());  // Saved in case scratch2 == a1.
1372662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ mov(a0, sp);  // (first argument - a0) = Handle<Name>
1373c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1374c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  const int kApiStackSpace = 1;
1375c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  FrameScope frame_scope(masm(), StackFrame::MANUAL);
1376c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ EnterExitFrame(false, kApiStackSpace);
1377c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1378fb7a7c4ffde9a4d060f5f989371e2ce964ee5831jkummerow@chromium.org  // Create PropertyAccessorInfo instance on the stack above the exit frame with
1379f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // scratch2 (internal::Object** args_) as the data.
1380c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ sw(a2, MemOperand(sp, kPointerSize));
1381662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  // (second argument - a1) = AccessorInfo&
1382662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  __ Addu(a1, sp, kPointerSize);
1383c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1384528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
1385662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  Address getter_address = v8::ToCData<Address>(callback->getter());
1386c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ApiFunction fun(getter_address);
1387662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
1388fe578677d80b14b35f6dca0c193719331b81a81edanno@chromium.org  ExternalReference ref = ExternalReference(&fun, type, isolate());
1389b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
1390662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
1391b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  ExternalReference::Type thunk_type =
1392662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org      ExternalReference::PROFILING_GETTER_CALL;
1393b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  ApiFunction thunk_fun(thunk_address);
1394b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type,
1395b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org      isolate());
1396bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ CallApiFunctionAndReturn(ref,
1397b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org                              getter_address,
1398b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org                              thunk_ref,
1399662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org                              a2,
1400bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org                              kStackUnwindSpace,
1401528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                              MemOperand(fp, 6 * kPointerSize),
1402528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                              NULL);
14035c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
14045c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14055c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14062efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadInterceptor(
14074a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Register holder_reg,
1408b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    Handle<Object> object,
14094a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Handle<JSObject> interceptor_holder,
14104a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    LookupResult* lookup,
14119faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Handle<Name> name) {
1412c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(interceptor_holder->HasNamedInterceptor());
1413c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1414c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1415c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // So far the most popular follow ups for interceptor loads are FIELD
1416c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // and CALLBACKS, so inline only them, other cases may be added
1417c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // later.
1418c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  bool compile_followup_inline = false;
141905ed9ddc6ff3a1ab3983c50d378cddfa257869b6jkummerow@chromium.org  if (lookup->IsFound() && lookup->IsCacheable()) {
1420de0db002768654f346a9059d80ab47602018bfa0yangguo@chromium.org    if (lookup->IsField()) {
1421c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      compile_followup_inline = true;
1422c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    } else if (lookup->type() == CALLBACKS &&
1423c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org        lookup->GetCallbackObject()->IsExecutableAccessorInfo()) {
1424c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org      ExecutableAccessorInfo* callback =
1425c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org          ExecutableAccessorInfo::cast(lookup->GetCallbackObject());
14267028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      compile_followup_inline = callback->getter() != NULL &&
14277028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          callback->IsCompatibleReceiver(*object);
1428c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
1429c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1430c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1431c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (compile_followup_inline) {
1432c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Compile the interceptor call, followed by inline code to load the
1433c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // property from further up the prototype chain if the call fails.
1434c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Check that the maps haven't changed.
14354a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
1436c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1437212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    // Preserve the receiver register explicitly whenever it is different from
1438212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    // the holder and it is needed should the interceptor return without any
1439212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    // result. The CALLBACKS case needs the receiver to be passed into C++ code,
1440212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    // the FIELD case might cause a miss during the prototype check.
1441212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org    bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
14424a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    bool must_preserve_receiver_reg = !receiver().is(holder_reg) &&
1443212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org        (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
1444212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org
1445c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Save necessary data before invoking an interceptor.
1446c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Requires a frame to make GC aware of pushed pointers.
1447c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
1448c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FrameScope frame_scope(masm(), StackFrame::INTERNAL);
1449212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org      if (must_preserve_receiver_reg) {
14504a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org        __ Push(receiver(), holder_reg, this->name());
1451c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      } else {
14524a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org        __ Push(holder_reg, this->name());
1453c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
1454c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Invoke an interceptor.  Note: map checks from receiver to
1455c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // interceptor's holder has been compiled before (see a caller
1456c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // of this method).
145737be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      CompileCallLoadPropertyWithInterceptor(
145837be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org          masm(), receiver(), holder_reg, this->name(), interceptor_holder,
145937be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org          IC::kLoadPropertyWithInterceptorOnly);
146037be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org
1461c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Check if interceptor provided a value for property.  If it's
1462c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // the case, return immediately.
1463c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Label interceptor_failed;
14644a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex);
14654a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      __ Branch(&interceptor_failed, eq, v0, Operand(scratch1()));
1466c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      frame_scope.GenerateLeaveFrame();
1467c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Ret();
1468c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1469c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ bind(&interceptor_failed);
14704a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      __ pop(this->name());
1471c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ pop(holder_reg);
1472212d964d8f853ddb1fdf3a64037f3af294d55cf3jkummerow@chromium.org      if (must_preserve_receiver_reg) {
14734a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org        __ pop(receiver());
1474c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
1475c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Leave the internal frame.
1476c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
14774a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup);
1478c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {  // !compile_followup_inline
1479c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Call the runtime system to load the interceptor.
1480c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Check that the maps haven't changed.
14814a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    PushInterceptorArguments(masm(), receiver(), holder_reg,
14824a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                             this->name(), interceptor_holder);
1483c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1484c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    ExternalReference ref = ExternalReference(
148532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate());
14864a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1);
1487c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
14885c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
14895c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14905c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14919faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.orgvoid CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
1492c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (kind_ == Code::KEYED_CALL_IC) {
1493394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ Branch(miss, ne, a2, Operand(name));
1494c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
14957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
14965d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org
14975d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org
14988a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.orgvoid CallStubCompiler::GenerateFunctionCheck(Register function,
14998a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                                             Register scratch,
15008a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                                             Label* miss) {
15018a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  __ JumpIfSmi(function, miss);
15028a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  __ GetObjectType(function, scratch, scratch);
15038a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  __ Branch(miss, ne, scratch, Operand(JS_FUNCTION_TYPE));
15048a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org}
15058a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org
15068a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org
1507c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid CallStubCompiler::GenerateLoadFunctionFromCell(
1508f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org    Handle<Cell> cell,
1509c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
1510c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Label* miss) {
1511c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the value from the cell.
1512c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ li(a3, Operand(cell));
1513f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org  __ lw(a1, FieldMemOperand(a3, Cell::kValueOffset));
1514c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1515c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the cell contains the same function.
1516c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (heap()->InNewSpace(*function)) {
1517c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // We can't embed a pointer to a function in new space so we have
1518c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // to verify that the shared function info is unchanged. This has
1519c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // the nice side effect that multiple closures based on the same
1520c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // function can all use this call IC. Before we load through the
1521c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // function, we have to verify that it still is a function.
15228a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org    GenerateFunctionCheck(a1, a3, miss);
1523c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1524c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Check the shared function info. Make sure it hasn't changed.
1525c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ li(a3, Handle<SharedFunctionInfo>(function->shared()));
1526c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1527c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Branch(miss, ne, t0, Operand(a3));
1528c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
1529c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    __ Branch(miss, ne, a1, Operand(function));
1530c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
15315c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15325c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15335c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1534394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.comvoid CallStubCompiler::GenerateMissBranch() {
1535394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Handle<Code> code =
153640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org      isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
153740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                                               kind_,
1538ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org                                               extra_state());
1539394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ Jump(code, RelocInfo::CODE_TARGET);
1540394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
1541394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1542394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
1543394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.comHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
1544394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                                Handle<JSObject> holder,
1545fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                PropertyIndex index,
15469faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                Handle<Name> name) {
1547c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss;
1548c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1549cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  Register reg = HandlerFrontendHeader(
1550cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      object, holder, name, RECEIVER_MAP_CHECK, &miss);
155157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  GenerateFastPropertyLoad(masm(), a1, reg, index.is_inobject(holder),
155257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                           index.translate(holder), Representation::Tagged());
15538a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateJumpFunction(object, a1, &miss);
1554c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1555cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
1556c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1557c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
15589af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(Code::FAST, name);
15595d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org}
15605d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org
15615d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org
15621510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgHandle<Code> CallStubCompiler::CompileArrayCodeCall(
15631510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<Object> object,
15641510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<JSObject> holder,
15651510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<Cell> cell,
15661510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<JSFunction> function,
15671510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
15681510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
15691510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  Label miss;
15701510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
1571cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1572cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  if (!cell.is_null()) {
15731510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    ASSERT(cell->value() == *function);
15741510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    GenerateLoadFunctionFromCell(cell, function, &miss);
15751510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  }
15761510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
1577bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
1578b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  site->SetElementsKind(GetInitialFastElementsKind());
1579bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
1580cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  const int argc = arguments().immediate();
15811510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ li(a0, Operand(argc));
1582bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ li(a2, Operand(site_feedback_cell));
15831510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ li(a1, Operand(function));
15841510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
15851510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ArrayConstructorStub stub(isolate());
15861510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ TailCallStub(&stub);
15871510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
1588cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
15891510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
15901510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Return the generated code.
15911510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
15921510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org}
15931510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
15941510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
1595c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileArrayPushCall(
1596c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
1597c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
1598f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org    Handle<Cell> cell,
1599c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
16001510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
16011510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
16028a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // If object is not an array or is observed or sealed, bail out to regular
16038a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // call.
1604b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  if (!object->IsJSArray() ||
1605b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org      !cell.is_null() ||
16068a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org      Handle<JSArray>::cast(object)->map()->is_observed() ||
16078a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org      !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1608b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    return Handle<Code>::null();
1609b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  }
16105c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1611c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss;
1612cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1613cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  Register receiver = a0;
1614cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  Register scratch = a1;
16155c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1616c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  const int argc = arguments().immediate();
1617c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1618c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (argc == 0) {
1619c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Nothing to do, just return the length.
1620c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
16218a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org    __ DropAndRet(argc + 1);
1622c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
1623c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Label call_builtin;
1624c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (argc == 1) {  // Otherwise fall through to call the builtin.
16258e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org      Label attempt_to_grow_elements, with_write_barrier, check_double;
1626c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
162778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      Register elements = t2;
162878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      Register end_elements = t1;
162978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      // Get the elements array of the object.
163078d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
163178d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org
163278d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      // Check that the elements are in fast mode and writable.
163378d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ CheckMap(elements,
1634cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org                  scratch,
163578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org                  Heap::kFixedArrayMapRootIndex,
16368e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org                  &check_double,
163778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org                  DONT_DO_SMI_CHECK);
163878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org
1639cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      // Get the array's length into scratch and calculate new length.
1640cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ lw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1641c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      STATIC_ASSERT(kSmiTagSize == 1);
1642c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      STATIC_ASSERT(kSmiTag == 0);
1643cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ Addu(scratch, scratch, Operand(Smi::FromInt(argc)));
1644c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
164578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      // Get the elements' length.
1646c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset));
1647c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1648c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Check if we could survive without allocation.
1649cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ Branch(&attempt_to_grow_elements, gt, scratch, Operand(t0));
1650c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1651b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      // Check if value is a smi.
1652b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize));
1653b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ JumpIfNotSmi(t0, &with_write_barrier);
1654b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org
1655c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Save new length.
1656cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1657c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
165878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      // Store the value.
1659c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // We may need a register containing the address end_elements below,
1660c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // so write back the value in end_elements.
1661cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize);
1662c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ Addu(end_elements, elements, end_elements);
1663c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      const int kEndElementsOffset =
1664c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
1665c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Addu(end_elements, end_elements, kEndElementsOffset);
1666c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sw(t0, MemOperand(end_elements));
1667c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1668c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Check for a smi.
1669cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ mov(v0, scratch);
16708a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org      __ DropAndRet(argc + 1);
1671c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
16728e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org      __ bind(&check_double);
16738e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
16748e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org      // Check that the elements are in fast mode and writable.
16758e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org      __ CheckMap(elements,
1676cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org                  scratch,
16778e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org                  Heap::kFixedDoubleArrayMapRootIndex,
16788e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org                  &call_builtin,
16798e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org                  DONT_DO_SMI_CHECK);
16808e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
1681cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      // Get the array's length into scratch and calculate new length.
1682cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ lw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
16838e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org      STATIC_ASSERT(kSmiTagSize == 1);
16848e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org      STATIC_ASSERT(kSmiTag == 0);
1685cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ Addu(scratch, scratch, Operand(Smi::FromInt(argc)));
16868e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
16878e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org      // Get the elements' length.
16888e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org      __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset));
16898e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
16908e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org      // Check if we could survive without allocation.
1691cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ Branch(&call_builtin, gt, scratch, Operand(t0));
16928e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
16938e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org      __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize));
16948e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org      __ StoreNumberToDoubleElements(
1695cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org          t0, scratch, elements, a3, t1, a2,
16968e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org          &call_builtin, argc * kDoubleSize);
16978e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
16988e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org      // Save new length.
1699cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
17008e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
1701cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ mov(v0, scratch);
17028a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org      __ DropAndRet(argc + 1);
17038e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
1704c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ bind(&with_write_barrier);
1705b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org
170678d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ lw(a3, FieldMemOperand(receiver, HeapObject::kMapOffset));
170778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org
170878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      if (FLAG_smi_only_arrays  && !FLAG_trace_elements_transitions) {
170978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        Label fast_object, not_fast_object;
171078d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        __ CheckFastObjectElements(a3, t3, &not_fast_object);
171178d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        __ jmp(&fast_object);
171278d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        // In case of fast smi-only, convert to fast object, otherwise bail out.
171378d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        __ bind(&not_fast_object);
1714830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        __ CheckFastSmiElements(a3, t3, &call_builtin);
17158e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
17168e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org        __ lw(t3, FieldMemOperand(t0, HeapObject::kMapOffset));
17178e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org        __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
17188e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org        __ Branch(&call_builtin, eq, t3, Operand(at));
171978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        // edx: receiver
17208e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org        // a3: map
1721830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        Label try_holey_map;
1722830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
172378d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org                                               FAST_ELEMENTS,
172478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org                                               a3,
172578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org                                               t3,
1726830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                               &try_holey_map);
1727830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        __ mov(a2, receiver);
1728830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        ElementsTransitionGenerator::
172928381b491d5ea9f256a3937000de7953639ef93fyangguo@chromium.org            GenerateMapChangeElementsTransition(masm(),
173028381b491d5ea9f256a3937000de7953639ef93fyangguo@chromium.org                                                DONT_TRACK_ALLOCATION_SITE,
173128381b491d5ea9f256a3937000de7953639ef93fyangguo@chromium.org                                                NULL);
1732830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        __ jmp(&fast_object);
1733830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org
1734830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        __ bind(&try_holey_map);
1735830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
1736830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                               FAST_HOLEY_ELEMENTS,
1737830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                               a3,
1738830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org                                               t3,
173978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org                                               &call_builtin);
174078d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        __ mov(a2, receiver);
1741830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org        ElementsTransitionGenerator::
174228381b491d5ea9f256a3937000de7953639ef93fyangguo@chromium.org            GenerateMapChangeElementsTransition(masm(),
174328381b491d5ea9f256a3937000de7953639ef93fyangguo@chromium.org                                                DONT_TRACK_ALLOCATION_SITE,
174428381b491d5ea9f256a3937000de7953639ef93fyangguo@chromium.org                                                NULL);
174578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        __ bind(&fast_object);
174678d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      } else {
174778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        __ CheckFastObjectElements(a3, a3, &call_builtin);
174878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      }
1749b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org
1750b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      // Save new length.
1751cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1752b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org
175378d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      // Store the value.
1754b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      // We may need a register containing the address end_elements below,
1755b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      // so write back the value in end_elements.
1756cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize);
1757b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ Addu(end_elements, elements, end_elements);
1758b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ Addu(end_elements, end_elements, kEndElementsOffset);
1759b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ sw(t0, MemOperand(end_elements));
1760b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org
1761b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ RecordWrite(elements,
1762b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org                     end_elements,
1763b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org                     t0,
1764b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org                     kRAHasNotBeenSaved,
1765b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org                     kDontSaveFPRegs,
1766b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org                     EMIT_REMEMBERED_SET,
1767b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org                     OMIT_SMI_CHECK);
1768cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ mov(v0, scratch);
17698a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org      __ DropAndRet(argc + 1);
1770c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1771c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ bind(&attempt_to_grow_elements);
1772cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      // scratch: array's length + 1.
1773c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // t0: elements' length.
1774c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1775c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      if (!FLAG_inline_new) {
1776c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        __ Branch(&call_builtin);
1777c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      }
1778c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1779b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ lw(a2, MemOperand(sp, (argc - 1) * kPointerSize));
1780b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      // Growing elements that are SMI-only requires special handling in case
1781b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      // the new element is non-Smi. For now, delegate to the builtin.
1782b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      Label no_fast_elements_check;
1783b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ JumpIfSmi(a2, &no_fast_elements_check);
1784b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset));
1785b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ CheckFastObjectElements(t3, t3, &call_builtin);
1786b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ bind(&no_fast_elements_check);
1787b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org
1788c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      ExternalReference new_space_allocation_top =
178932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org          ExternalReference::new_space_allocation_top_address(isolate());
1790c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      ExternalReference new_space_allocation_limit =
179132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org          ExternalReference::new_space_allocation_limit_address(isolate());
1792c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1793c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      const int kAllocationDelta = 4;
1794c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Load top and check if it is the end of elements.
1795cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize);
1796c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ Addu(end_elements, elements, end_elements);
1797c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ Addu(end_elements, end_elements, Operand(kEndElementsOffset));
1798c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ li(t3, Operand(new_space_allocation_top));
179978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ lw(a3, MemOperand(t3));
180078d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ Branch(&call_builtin, ne, end_elements, Operand(a3));
1801c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1802c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ li(t5, Operand(new_space_allocation_limit));
1803c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ lw(t5, MemOperand(t5));
180478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ Addu(a3, a3, Operand(kAllocationDelta * kPointerSize));
180578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ Branch(&call_builtin, hi, a3, Operand(t5));
1806c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1807c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // We fit and could grow elements.
1808c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Update new_space_allocation_top.
180978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ sw(a3, MemOperand(t3));
1810c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Push the argument.
1811b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ sw(a2, MemOperand(end_elements));
1812c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Fill the rest with holes.
181378d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org      __ LoadRoot(a3, Heap::kTheHoleValueRootIndex);
1814c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      for (int i = 1; i < kAllocationDelta; i++) {
181578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org        __ sw(a3, MemOperand(end_elements, i * kPointerSize));
1816c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      }
1817c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1818c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Update elements' and array's sizes.
1819cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
1820c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta)));
1821c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset));
1822c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1823c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Elements are in new space, so write barrier is not required.
1824cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ mov(v0, scratch);
18258a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org      __ DropAndRet(argc + 1);
1826c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
1827c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind(&call_builtin);
182832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    __ TailCallExternalReference(
182932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1);
1830c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1831c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1832cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
1833c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1834c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
18351510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
1836c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
1837c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1838c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1839c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileArrayPopCall(
1840c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
1841c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
1842f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org    Handle<Cell> cell,
1843c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
18441510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
18451510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
18468a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // If object is not an array or is observed or sealed, bail out to regular
18478a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // call.
1848b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  if (!object->IsJSArray() ||
1849b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org      !cell.is_null() ||
18508a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org      Handle<JSArray>::cast(object)->map()->is_observed() ||
18518a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org      !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1852b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    return Handle<Code>::null();
1853b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  }
1854c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1855c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss, return_undefined, call_builtin;
1856cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  Register receiver = a0;
1857cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  Register scratch = a1;
1858c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Register elements = a3;
1859cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1860c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1861c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the elements array of the object.
1862c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
1863c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1864c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the elements are in fast mode and writable.
186540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  __ CheckMap(elements,
1866cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org              scratch,
186740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org              Heap::kFixedArrayMapRootIndex,
186840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org              &call_builtin,
186940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org              DONT_DO_SMI_CHECK);
1870c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1871c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the array's length into t0 and calculate new length.
1872c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset));
1873c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Subu(t0, t0, Operand(Smi::FromInt(1)));
1874c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&return_undefined, lt, t0, Operand(zero_reg));
1875c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1876c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the last element.
1877c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ LoadRoot(t2, Heap::kTheHoleValueRootIndex);
1878c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  STATIC_ASSERT(kSmiTagSize == 1);
1879c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  STATIC_ASSERT(kSmiTag == 0);
1880c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // We can't address the last element in one operation. Compute the more
1881c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // expensive shift first, and use an offset later on.
1882c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ sll(t1, t0, kPointerSizeLog2 - kSmiTagSize);
1883c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(elements, elements, t1);
1884cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  __ lw(scratch, FieldMemOperand(elements, FixedArray::kHeaderSize));
1885cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  __ Branch(&call_builtin, eq, scratch, Operand(t2));
1886c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1887c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Set the array's length.
1888c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset));
1889c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1890c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Fill with the hole.
18917d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  __ sw(t2, FieldMemOperand(elements, FixedArray::kHeaderSize));
1892cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  const int argc = arguments().immediate();
1893cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  __ mov(v0, scratch);
18948a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ DropAndRet(argc + 1);
1895c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1896c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&return_undefined);
1897c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
18988a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ DropAndRet(argc + 1);
1899c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1900c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&call_builtin);
190132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  __ TailCallExternalReference(
190232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1);
1903c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1904cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
1905c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1906c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
19071510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
1908c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org}
1909c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1910c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1911c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
1912c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
1913c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
1914f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org    Handle<Cell> cell,
1915c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
19161510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
19171510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
1918c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If object is not a string, bail out to regular call.
1919c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
1920c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1921c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss;
1922c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label name_miss;
1923c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label index_out_of_range;
1924c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1925c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label* index_out_of_range_label = &index_out_of_range;
1926c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
192740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  if (kind_ == Code::CALL_IC &&
1928ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      (CallICBase::StringStubState::decode(extra_state()) ==
192940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org       DEFAULT_STRING_STUB)) {
1930c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    index_out_of_range_label = &miss;
1931c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1932c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1933cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
1934c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1935cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  Register receiver = a0;
1936c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Register index = t1;
1937cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  Register result = a1;
1938cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  const int argc = arguments().immediate();
1939c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(receiver, MemOperand(sp, argc * kPointerSize));
1940c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (argc > 0) {
1941c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize));
1942c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
1943c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
1944c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1945c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1946c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  StringCharCodeAtGenerator generator(receiver,
1947c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                      index,
1948c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                      result,
1949c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                      &miss,  // When not a string.
1950c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                      &miss,  // When not a number.
1951c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                      index_out_of_range_label,
1952c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                      STRING_INDEX_IS_NUMBER);
1953c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  generator.GenerateFast(masm());
1954cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  __ mov(v0, result);
19558a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ DropAndRet(argc + 1);
1956c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1957c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  StubRuntimeCallHelper call_helper;
1958c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  generator.GenerateSlow(masm(), call_helper);
1959c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1960c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (index_out_of_range.is_linked()) {
1961c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind(&index_out_of_range);
1962c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ LoadRoot(v0, Heap::kNanValueRootIndex);
19638a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org    __ DropAndRet(argc + 1);
1964c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1965c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1966c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&miss);
1967c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Restore function name in a2.
1968c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ li(a2, name);
19698a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  HandlerFrontendFooter(&name_miss);
1970c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1971c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
19721510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
19735c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
19745c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19755c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1976c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileStringCharAtCall(
1977c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
1978c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
1979f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org    Handle<Cell> cell,
1980c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
19811510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
19821510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
1983c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If object is not a string, bail out to regular call.
1984c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
1985c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1986c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  const int argc = arguments().immediate();
1987c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss;
1988c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label name_miss;
1989c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label index_out_of_range;
1990c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label* index_out_of_range_label = &index_out_of_range;
199140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  if (kind_ == Code::CALL_IC &&
1992ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org      (CallICBase::StringStubState::decode(extra_state()) ==
199340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org       DEFAULT_STRING_STUB)) {
1994c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    index_out_of_range_label = &miss;
1995c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1996c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1997cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
1998cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org
1999cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  Register receiver = a0;
2000c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Register index = t1;
2001c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  Register scratch = a3;
2002cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  Register result = a1;
2003c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (argc > 0) {
2004c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize));
2005c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
2006c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
2007c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
2008c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2009c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  StringCharAtGenerator generator(receiver,
2010c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                  index,
2011c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org                                  scratch,
2012c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                  result,
2013c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                  &miss,  // When not a string.
2014c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                  &miss,  // When not a number.
2015c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                  index_out_of_range_label,
2016c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                  STRING_INDEX_IS_NUMBER);
2017c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  generator.GenerateFast(masm());
2018cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  __ mov(v0, result);
20198a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ DropAndRet(argc + 1);
2020c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2021c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  StubRuntimeCallHelper call_helper;
2022c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  generator.GenerateSlow(masm(), call_helper);
2023c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2024c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (index_out_of_range.is_linked()) {
2025c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind(&index_out_of_range);
2026750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    __ LoadRoot(v0, Heap::kempty_stringRootIndex);
20278a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org    __ DropAndRet(argc + 1);
2028c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
2029c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2030c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&miss);
2031c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Restore function name in a2.
2032c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ li(a2, name);
20338a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  HandlerFrontendFooter(&name_miss);
2034c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2035c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
20361510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
20375c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
20385c838251403b0be9a882540f1922577abba4c872ager@chromium.org
20395c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2040c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
2041c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
2042c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
2043f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org    Handle<Cell> cell,
2044c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
20451510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
20461510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
2047c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  const int argc = arguments().immediate();
2048c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2049c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If the object is not a JSObject or we got an unexpected number of
2050c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // arguments, bail out to the regular call.
2051c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2052c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2053c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss;
2054cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2055cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  if (!cell.is_null()) {
2056c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    ASSERT(cell->value() == *function);
2057c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    GenerateLoadFunctionFromCell(cell, function, &miss);
2058c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
2059c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2060c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load the char code argument.
2061c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Register code = a1;
2062c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(code, MemOperand(sp, 0 * kPointerSize));
2063c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2064c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check the code is a smi.
2065c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label slow;
2066c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  STATIC_ASSERT(kSmiTag == 0);
2067c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ JumpIfNotSmi(code, &slow);
2068c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2069c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Convert the smi code to uint16.
2070c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ And(code, code, Operand(Smi::FromInt(0xffff)));
2071c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2072c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  StringCharFromCodeGenerator generator(code, v0);
2073c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  generator.GenerateFast(masm());
20748a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ DropAndRet(argc + 1);
2075c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2076c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  StubRuntimeCallHelper call_helper;
2077c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  generator.GenerateSlow(masm(), call_helper);
2078c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2079c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&slow);
20808a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // We do not have to patch the receiver because the function makes no use of
20818a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // it.
20828a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateJumpFunctionIgnoreReceiver(function);
2083c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2084cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
2085c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2086c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
20871510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
20885c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
20895c838251403b0be9a882540f1922577abba4c872ager@chromium.org
20905c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2091c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileMathFloorCall(
2092c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
2093c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
2094f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org    Handle<Cell> cell,
2095c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
20961510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
20971510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
2098c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  const int argc = arguments().immediate();
2099c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If the object is not a JSObject or we got an unexpected number of
2100c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // arguments, bail out to the regular call.
2101c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2102c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2103c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss, slow;
2104cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2105cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  if (!cell.is_null()) {
2106c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    ASSERT(cell->value() == *function);
2107c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    GenerateLoadFunctionFromCell(cell, function, &miss);
2108c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
2109c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2110c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load the (only) argument into v0.
2111c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(v0, MemOperand(sp, 0 * kPointerSize));
2112c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2113c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If the argument is a smi, just return.
2114c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  STATIC_ASSERT(kSmiTag == 0);
21157ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ SmiTst(v0, t0);
21168a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ DropAndRet(argc + 1, eq, t0, Operand(zero_reg));
2117c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
211840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
2119c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2120c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label wont_fit_smi, no_fpu_error, restore_fcsr_and_return;
2121c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2122c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If fpu is enabled, we use the floor instruction.
2123c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2124c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load the HeapNumber value.
2125c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ ldc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset));
2126c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2127c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Backup FCSR.
2128c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ cfc1(a3, FCSR);
2129c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Clearing FCSR clears the exception mask with no side-effects.
2130c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ ctc1(zero_reg, FCSR);
2131c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Convert the argument to an integer.
2132c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ floor_w_d(f0, f0);
2133c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2134c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Start checking for special cases.
2135c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the argument exponent and clear the sign bit.
2136c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(t1, FieldMemOperand(v0, HeapNumber::kValueOffset + kPointerSize));
2137c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ And(t2, t1, Operand(~HeapNumber::kSignMask));
2138c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ srl(t2, t2, HeapNumber::kMantissaBitsInTopWord);
2139c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2140c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Retrieve FCSR and check for fpu errors.
2141c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ cfc1(t5, FCSR);
2142d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  __ And(t5, t5, Operand(kFCSRExceptionFlagMask));
2143c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&no_fpu_error, eq, t5, Operand(zero_reg));
2144c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2145c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check for NaN, Infinity, and -Infinity.
2146c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // They are invariant through a Math.Floor call, so just
2147c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // return the original argument.
2148c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Subu(t3, t2, Operand(HeapNumber::kExponentMask
2149c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        >> HeapNumber::kMantissaBitsInTopWord));
2150c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&restore_fcsr_and_return, eq, t3, Operand(zero_reg));
2151c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // We had an overflow or underflow in the conversion. Check if we
2152c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // have a big exponent.
2153c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If greater or equal, the argument is already round and in v0.
2154c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&restore_fcsr_and_return, ge, t3,
2155c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      Operand(HeapNumber::kMantissaBits));
2156c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&wont_fit_smi);
2157c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2158c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&no_fpu_error);
2159c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Move the result back to v0.
2160c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ mfc1(v0, f0);
2161c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check if the result fits into a smi.
2162c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(a1, v0, Operand(0x40000000));
2163c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&wont_fit_smi, lt, a1, Operand(zero_reg));
2164c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Tag the result.
2165c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  STATIC_ASSERT(kSmiTag == 0);
2166c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ sll(v0, v0, kSmiTagSize);
2167c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2168c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check for -0.
2169c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&restore_fcsr_and_return, ne, v0, Operand(zero_reg));
2170c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // t1 already holds the HeapNumber exponent.
2171c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ And(t0, t1, Operand(HeapNumber::kSignMask));
2172c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If our HeapNumber is negative it was -0, so load its address and return.
2173c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Else v0 is loaded with 0, so we can also just return.
2174c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&restore_fcsr_and_return, eq, t0, Operand(zero_reg));
2175c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(v0, MemOperand(sp, 0 * kPointerSize));
2176c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2177c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&restore_fcsr_and_return);
2178c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Restore FCSR and return.
2179c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ ctc1(a3, FCSR);
2180c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
21818a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ DropAndRet(argc + 1);
2182c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2183c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&wont_fit_smi);
2184c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Restore FCSR and fall to slow case.
2185c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ ctc1(a3, FCSR);
2186c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2187c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&slow);
21888a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // We do not have to patch the receiver because the function makes no use of
21898a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // it.
21908a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateJumpFunctionIgnoreReceiver(function);
2191c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2192cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
2193c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2194c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
21951510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
21965c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
21975c838251403b0be9a882540f1922577abba4c872ager@chromium.org
21985c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2199c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileMathAbsCall(
2200c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
2201c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
2202f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org    Handle<Cell> cell,
2203c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
22041510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Handle<String> name,
22051510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Code::StubType type) {
2206c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  const int argc = arguments().immediate();
2207c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If the object is not a JSObject or we got an unexpected number of
2208c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // arguments, bail out to the regular call.
2209c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2210c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2211c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss;
2212c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2213cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2214cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  if (!cell.is_null()) {
2215c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    ASSERT(cell->value() == *function);
2216c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    GenerateLoadFunctionFromCell(cell, function, &miss);
2217c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
2218c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2219c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Load the (only) argument into v0.
2220c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(v0, MemOperand(sp, 0 * kPointerSize));
2221c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2222c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check if the argument is a smi.
2223c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label not_smi;
2224c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  STATIC_ASSERT(kSmiTag == 0);
2225c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ JumpIfNotSmi(v0, &not_smi);
2226c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2227c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Do bitwise not or do nothing depending on the sign of the
2228c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // argument.
2229c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ sra(t0, v0, kBitsPerInt - 1);
2230c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Xor(a1, v0, t0);
2231c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2232c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Add 1 or do nothing depending on the sign of the argument.
2233c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Subu(v0, a1, t0);
2234c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2235c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If the result is still negative, go to the slow case.
2236c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // This only happens for the most negative smi.
2237c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label slow;
2238c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&slow, lt, v0, Operand(zero_reg));
2239c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2240c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Smi case done.
22418a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ DropAndRet(argc + 1);
2242c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2243c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check if the argument is a heap number and load its exponent and
2244c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // sign.
2245c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&not_smi);
224640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
2247c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset));
2248c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2249c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check the sign of the argument. If the argument is positive,
2250c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // just return it.
2251c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label negative_sign;
2252c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ And(t0, a1, Operand(HeapNumber::kSignMask));
2253c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&negative_sign, ne, t0, Operand(zero_reg));
22548a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ DropAndRet(argc + 1);
2255c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2256c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If the argument is negative, clear the sign, and return a new
2257c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // number.
2258c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&negative_sign);
2259c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Xor(a1, a1, Operand(HeapNumber::kSignMask));
2260c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset));
2261c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex);
2262c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ AllocateHeapNumber(v0, t0, t1, t2, &slow);
2263c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ sw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset));
2264c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset));
22658a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ DropAndRet(argc + 1);
2266c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2267c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&slow);
22688a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // We do not have to patch the receiver because the function makes no use of
22698a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // it.
22708a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateJumpFunctionIgnoreReceiver(function);
2271c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2272cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
2273c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2274c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
22751510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  return GetCode(type, name);
22765c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
22775c838251403b0be9a882540f1922577abba4c872ager@chromium.org
22785c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2279c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileFastApiCall(
22807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    const CallOptimization& optimization,
2281c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<Object> object,
2282c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> holder,
2283f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org    Handle<Cell> cell,
2284c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
2285c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<String> name) {
2286c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
228740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  Counters* counters = isolate()->counters();
2288c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2289c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(optimization.is_simple_api_call());
2290c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Bail out if object is a global object as we don't want to
2291c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // repatch it to global receiver.
2292c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (object->IsGlobalObject()) return Handle<Code>::null();
2293c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (!cell.is_null()) return Handle<Code>::null();
2294c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (!object->IsJSObject()) return Handle<Code>::null();
2295c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  int depth = optimization.GetPrototypeDepthOfExpectedType(
2296c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      Handle<JSObject>::cast(object), holder);
2297c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  if (depth == kInvalidProtoDepth) return Handle<Code>::null();
2298c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2299c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss, miss_before_stack_reserved;
2300c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2301c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  GenerateNameCheck(name, &miss_before_stack_reserved);
2302c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2303c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the receiver from the stack.
2304c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  const int argc = arguments().immediate();
2305c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a1, MemOperand(sp, argc * kPointerSize));
2306c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2307c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the receiver isn't a smi.
2308c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ JumpIfSmi(a1, &miss_before_stack_reserved);
2309c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2310c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ IncrementCounter(counters->call_const(), 1, a0, a3);
2311c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a3);
2312c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2313c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ReserveSpaceForFastApiCall(masm(), a0);
2314c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2315c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the maps haven't changed and find a Holder as a side effect.
2316f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  CheckPrototypes(
2317f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      IC::CurrentTypeOf(object, isolate()),
2318f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      a1, holder, a0, a3, t0, name, depth, &miss);
2319c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2320528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  GenerateFastApiDirectCall(masm(), optimization, argc, false);
2321c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2322c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&miss);
2323c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  FreeSpaceForFastApiCall(masm());
2324c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
23258a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  HandlerFrontendFooter(&miss_before_stack_reserved);
2326c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2327c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
2328c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  return GetCode(function);
23295c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
23305c838251403b0be9a882540f1922577abba4c872ager@chromium.org
23315c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2332b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.orgvoid StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
2333b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  Label success;
2334b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  // Check that the object is a boolean.
2335b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  __ LoadRoot(at, Heap::kTrueValueRootIndex);
2336b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  __ Branch(&success, eq, object, Operand(at));
2337b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  __ LoadRoot(at, Heap::kFalseValueRootIndex);
2338b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  __ Branch(miss, ne, object, Operand(at));
2339b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  __ bind(&success);
2340b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org}
2341b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org
2342b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org
2343cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.orgvoid CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
2344cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  if (object->IsGlobalObject()) {
2345cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org    const int argc = arguments().immediate();
2346cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org    const int receiver_offset = argc * kPointerSize;
2347cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org    __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset));
2348cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org    __ sw(a3, MemOperand(sp, receiver_offset));
2349cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  }
2350cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org}
2351cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org
2352cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org
2353cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.orgRegister CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
2354cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org                                                 Handle<JSObject> holder,
2355cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org                                                 Handle<Name> name,
2356cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org                                                 CheckType check,
2357cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org                                                 Label* miss) {
2358c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // ----------- S t a t e -------------
2359c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  //  -- a2    : name
2360c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  //  -- ra    : return address
2361c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // -----------------------------------
2362cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  GenerateNameCheck(name, miss);
2363cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org
2364cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  Register reg = a0;
2365c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2366c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the receiver from the stack.
2367c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  const int argc = arguments().immediate();
2368cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  const int receiver_offset = argc * kPointerSize;
2369cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  __ lw(a0, MemOperand(sp, receiver_offset));
2370c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2371c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the receiver isn't a smi.
2372c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (check != NUMBER_CHECK) {
2373cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org    __ JumpIfSmi(a0, miss);
2374c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
2375c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2376c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Make sure that it's okay not to patch the on stack receiver
2377c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // unless we're doing a receiver map check.
2378c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2379c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  switch (check) {
2380c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    case RECEIVER_MAP_CHECK:
2381cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ IncrementCounter(isolate()->counters()->call_const(), 1, a1, a3);
2382c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2383c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Check that the maps haven't changed.
2384cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      reg = CheckPrototypes(
2385f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org          IC::CurrentTypeOf(object, isolate()),
2386cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org          reg, holder, a1, a3, t0, name, miss);
2387c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      break;
2388c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2389f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    case STRING_CHECK: {
2390750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      // Check that the object is a string.
2391cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ GetObjectType(reg, a3, a3);
2392cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ Branch(miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE));
23932f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      // Check that the maps starting from the prototype haven't changed.
23942f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      GenerateDirectLoadGlobalFunctionPrototype(
2395cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org          masm(), Context::STRING_FUNCTION_INDEX, a1, miss);
2396c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      break;
2397f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    }
2398f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    case SYMBOL_CHECK: {
23999faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      // Check that the object is a symbol.
2400cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ GetObjectType(reg, a1, a3);
2401cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ Branch(miss, ne, a3, Operand(SYMBOL_TYPE));
2402f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      // Check that the maps starting from the prototype haven't changed.
2403f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      GenerateDirectLoadGlobalFunctionPrototype(
2404cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org          masm(), Context::SYMBOL_FUNCTION_INDEX, a1, miss);
24059faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      break;
2406f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    }
24072f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org    case NUMBER_CHECK: {
2408c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      Label fast;
24092f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      // Check that the object is a smi or a heap number.
2410cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ JumpIfSmi(reg, &fast);
2411cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ GetObjectType(reg, a3, a3);
2412cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ Branch(miss, ne, a3, Operand(HEAP_NUMBER_TYPE));
24132f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      __ bind(&fast);
24142f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      // Check that the maps starting from the prototype haven't changed.
24152f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      GenerateDirectLoadGlobalFunctionPrototype(
2416cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org          masm(), Context::NUMBER_FUNCTION_INDEX, a1, miss);
2417c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      break;
24182f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org    }
24192f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org    case BOOLEAN_CHECK: {
2420cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      GenerateBooleanCheck(reg, miss);
2421b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org
24222f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      // Check that the maps starting from the prototype haven't changed.
24232f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      GenerateDirectLoadGlobalFunctionPrototype(
2424cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org          masm(), Context::BOOLEAN_FUNCTION_INDEX, a1, miss);
2425c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      break;
2426c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
24272f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org  }
24282f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org
2429cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  if (check != RECEIVER_MAP_CHECK) {
2430cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org    Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
2431cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org    reg = CheckPrototypes(
2432cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org        IC::CurrentTypeOf(prototype, isolate()),
2433cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org        a1, holder, a1, a3, t0, name, miss);
2434cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  }
2435b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org
2436cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  return reg;
24372f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org}
24382f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org
24392f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org
24408a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.orgvoid CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
24418a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                                            Register function,
24428a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                                            Label* miss) {
24438a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  ASSERT(function.is(a1));
24448a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // Check that the function really is a function.
24458a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateFunctionCheck(function, a3, miss);
2446cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  PatchGlobalProxy(object);
24478a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // Invoke the function.
24488a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  __ InvokeFunction(a1, arguments(), JUMP_FUNCTION,
24498a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org                    NullCallWrapper(), call_kind());
24505c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
24515c838251403b0be9a882540f1922577abba4c872ager@chromium.org
24525c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2453c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
2454c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                                      Handle<JSObject> holder,
24559faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org                                                      Handle<Name> name) {
2456c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss;
2457c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2458c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  GenerateNameCheck(name, &miss);
2459c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2460c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the number of arguments.
2461c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  const int argc = arguments().immediate();
2462394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  LookupResult lookup(isolate());
2463c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  LookupPostInterceptor(holder, name, &lookup);
2464c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2465c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the receiver from the stack.
2466c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a1, MemOperand(sp, argc * kPointerSize));
2467c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2468ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org  CallInterceptorCompiler compiler(this, arguments(), a2, extra_state());
2469c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  compiler.Compile(masm(), object, holder, name, &lookup, a1, a3, t0, a0,
2470c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                   &miss);
2471c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2472c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Move returned value, the function to call, to a1.
2473c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ mov(a1, v0);
2474c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Restore receiver.
2475c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a0, MemOperand(sp, argc * kPointerSize));
2476c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
24778a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateJumpFunction(object, a1, &miss);
2478c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
24798a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  HandlerFrontendFooter(&miss);
2480c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2481c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
24829af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(Code::FAST, name);
24835c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
24845c838251403b0be9a882540f1922577abba4c872ager@chromium.org
24855c838251403b0be9a882540f1922577abba4c872ager@chromium.org
2486c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgHandle<Code> CallStubCompiler::CompileCallGlobal(
2487c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSObject> object,
2488c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<GlobalObject> holder,
2489b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    Handle<PropertyCell> cell,
2490c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    Handle<JSFunction> function,
24919faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Handle<Name> name) {
2492c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (HasCustomCallGenerator(function)) {
24939faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Handle<Code> code = CompileCustomCall(
24941510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org        object, holder, cell, function, Handle<String>::cast(name),
24951510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org        Code::NORMAL);
2496c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    // A null handle means bail out to the regular compiler code below.
2497c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    if (!code.is_null()) return code;
2498c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
2499c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2500c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss;
2501cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
25028a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // Potentially loads a closure that matches the shared function info of the
25038a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  // function, rather than function.
2504c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  GenerateLoadFunctionFromCell(cell, function, &miss);
250532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  Counters* counters = isolate()->counters();
2506c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ IncrementCounter(counters->call_global_inline(), 1, a3, t0);
25078a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  GenerateJumpFunction(object, a1, function);
2508cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  HandlerFrontendFooter(&miss);
2509c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2510c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
25117a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  return GetCode(Code::NORMAL, name);
25125c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
25135c838251403b0be9a882540f1922577abba4c872ager@chromium.org
25145c838251403b0be9a882540f1922577abba4c872ager@chromium.org
25156e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.comHandle<Code> StoreStubCompiler::CompileStoreCallback(
25164c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org    Handle<JSObject> object,
2517355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    Handle<JSObject> holder,
2518bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Handle<Name> name,
2519c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org    Handle<ExecutableAccessorInfo> callback) {
2520f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  HandlerFrontend(IC::CurrentTypeOf(object, isolate()),
2521f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                  receiver(), holder, name);
2522c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2523c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Stub never generated for non-global objects that require access
2524c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // checks.
2525355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
2526c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
25274c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org  __ push(receiver());  // Receiver.
25284c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org  __ li(at, Operand(callback));  // Callback info.
2529bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ push(at);
2530bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ li(at, Operand(name));
2531bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ Push(at, value());
2532c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2533c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Do tail-call to the runtime system.
2534c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ExternalReference store_callback_property =
253532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
2536c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ TailCallExternalReference(store_callback_property, 4, 1);
2537c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2538c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
25399af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
25407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
25417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
25427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2543639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.orgHandle<Code> StoreStubCompiler::CompileStoreCallback(
2544639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    Handle<JSObject> object,
2545639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    Handle<JSObject> holder,
2546639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    Handle<Name> name,
2547639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    const CallOptimization& call_optimization) {
2548f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  HandlerFrontend(IC::CurrentTypeOf(object, isolate()),
2549f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                  receiver(), holder, name);
2550639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
2551639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  Register values[] = { value() };
2552639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  GenerateFastApiCall(
2553639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org      masm(), call_optimization, receiver(), scratch3(), 1, values);
2554639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
2555639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org  // Return the generated code.
25569af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
2557639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org}
2558639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
2559639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org
256046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#undef __
256146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#define __ ACCESS_MASM(masm)
256246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
256346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
256446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.orgvoid StoreStubCompiler::GenerateStoreViaSetter(
256546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    MacroAssembler* masm,
2566619781ad24991bca2894d2f677ac960da366b11esvenpanne@chromium.org    Handle<JSFunction> setter) {
25677028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // ----------- S t a t e -------------
25687028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  //  -- a0    : value
25697028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  //  -- a1    : receiver
25707028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  //  -- a2    : name
25717028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  //  -- ra    : return address
25727028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // -----------------------------------
25737028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  {
257446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
25757028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
25767028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // Save value register, so we can restore it later.
25777028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ push(a0);
25787028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
257946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    if (!setter.is_null()) {
258046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      // Call the JavaScript setter with receiver and value on the stack.
258146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      __ push(a1);
258246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      __ push(a0);
258346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      ParameterCount actual(1);
258432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ParameterCount expected(setter);
258532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      __ InvokeFunction(setter, expected, actual,
258632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                        CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
258746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    } else {
258846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      // If we generate a global code snippet for deoptimization only, remember
258946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      // the place to continue after deoptimization.
259046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
259146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    }
25927028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
25937028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // We have to return the passed value, not the return value of the setter.
25947028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ pop(v0);
25957028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
25967028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // Restore context register.
25977028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
25987028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  }
25997028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  __ Ret();
260046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org}
260146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
260246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
260346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#undef __
260446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#define __ ACCESS_MASM(masm())
260546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
260646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org
26076e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.comHandle<Code> StoreStubCompiler::CompileStoreInterceptor(
26084c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org    Handle<JSObject> object,
26099faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Handle<Name> name) {
2610c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label miss;
2611c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2612c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that the map of the object hasn't changed.
26134c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org  __ CheckMap(receiver(), scratch1(), Handle<Map>(object->map()), &miss,
2614a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org              DO_SMI_CHECK);
2615c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2616c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Perform global security token check if needed.
26174c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org  if (object->IsJSGlobalProxy()) {
26184c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org    __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss);
2619c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
2620c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2621c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Stub is never generated for non-global objects that require access
2622c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // checks.
26234c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2624c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
26254c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org  __ Push(receiver(), this->name(), value());
2626c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2627c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Do tail-call to the runtime system.
2628c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ExternalReference store_ic_property =
262932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
2630cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  __ TailCallExternalReference(store_ic_property, 3, 1);
2631c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2632c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Handle store cache miss.
2633c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&miss);
26342bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  TailCallBuiltin(masm(), MissBuiltin(kind()));
2635c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2636c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
26379af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
26387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
26397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
26407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2641f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type,
2642f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                                      Handle<JSObject> last,
2643f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                                      Handle<Name> name) {
2644f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  NonexistentHandlerFrontend(type, last, name);
264594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org
2646c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return undefined if maps of the full prototype chain is still the same.
2647c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
2648c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Ret();
2649c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2650c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
26519af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  return GetCode(kind(), Code::FAST, name);
26527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
26537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
26547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
265594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.orgRegister* LoadStubCompiler::registers() {
265694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  // receiver, name, scratch1, scratch2, scratch3, scratch4.
265794b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  static Register registers[] = { a0, a2, a3, a1, t0, t1 };
265894b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  return registers;
265994b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org}
2660c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2661c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
266294b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.orgRegister* KeyedLoadStubCompiler::registers() {
266394b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  // receiver, name, scratch1, scratch2, scratch3, scratch4.
266494b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  static Register registers[] = { a1, a0, a2, a3, t0, t1 };
266594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  return registers;
26665c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
26675c838251403b0be9a882540f1922577abba4c872ager@chromium.org
26685c838251403b0be9a882540f1922577abba4c872ager@chromium.org
26692bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.orgRegister* StoreStubCompiler::registers() {
26702bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // receiver, name, value, scratch1, scratch2, scratch3.
26712bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  static Register registers[] = { a1, a2, a0, a3, t0, t1 };
26722bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  return registers;
26732bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org}
26742bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
26752bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
26762bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.orgRegister* KeyedStoreStubCompiler::registers() {
26772bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  // receiver, name, value, scratch1, scratch2, scratch3.
26782bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  static Register registers[] = { a2, a1, a0, a3, t0, t1 };
26792bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  return registers;
26802bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org}
26812bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
26822bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
26839faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.orgvoid KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
268494b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org                                              Register name_reg,
268594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org                                              Label* miss) {
268694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  __ Branch(miss, ne, name_reg, Operand(name));
26875c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
26885c838251403b0be9a882540f1922577abba4c872ager@chromium.org
26895c838251403b0be9a882540f1922577abba4c872ager@chromium.org
26902bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.orgvoid KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
26912bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                                               Register name_reg,
26922bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org                                               Label* miss) {
26932bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ Branch(miss, ne, name_reg, Operand(name));
26942bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org}
26952bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
26962bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org
2697de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org#undef __
2698de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org#define __ ACCESS_MASM(masm)
2699de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2700de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2701de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.orgvoid LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
27022efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org                                             Register receiver,
2703de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org                                             Handle<JSFunction> getter) {
2704de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  // ----------- S t a t e -------------
2705de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  //  -- a0    : receiver
2706de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  //  -- a2    : name
2707de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  //  -- ra    : return address
2708de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  // -----------------------------------
2709de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  {
2710de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
2711de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2712de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    if (!getter.is_null()) {
2713de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      // Call the JavaScript getter with the receiver on the stack.
27142efc3e46d2de48d8859520ee7fe035c02108509bmstarzinger@chromium.org      __ push(receiver);
2715de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      ParameterCount actual(0);
271632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ParameterCount expected(getter);
271732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      __ InvokeFunction(getter, expected, actual,
271832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                        CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
2719de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    } else {
2720de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      // If we generate a global code snippet for deoptimization only, remember
2721de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      // the place to continue after deoptimization.
2722de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org      masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
2723de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    }
2724de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2725de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    // Restore context register.
2726de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2727de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  }
2728de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  __ Ret();
2729de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org}
2730de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2731de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2732de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org#undef __
2733de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org#define __ ACCESS_MASM(masm())
2734de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
2735de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
27366e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.comHandle<Code> LoadStubCompiler::CompileLoadGlobal(
2737f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    Handle<Type> type,
27384a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Handle<GlobalObject> global,
2739b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org    Handle<PropertyCell> cell,
27409faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Handle<Name> name,
27416e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    bool is_dont_delete) {
2742b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  Label miss;
2743c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2744f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  HandlerFrontendHeader(type, receiver(), global, name, &miss);
2745c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2746c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Get the value from the cell.
27476e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com  __ li(a3, Operand(cell));
2748f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org  __ lw(t0, FieldMemOperand(a3, Cell::kValueOffset));
2749c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2750c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check for deleted property if property can actually be deleted.
2751c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (!is_dont_delete) {
2752c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2753c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Branch(&miss, eq, t0, Operand(at));
2754c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
2755c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2756b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  HandlerFrontendFooter(name, &miss);
27574a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
275832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  Counters* counters = isolate()->counters();
2759c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3);
27608a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ Ret(USE_DELAY_SLOT);
27614a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ mov(v0, t0);
2762c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2763c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
2764e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  return GetCode(kind(), Code::NORMAL, name);
27655c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
27667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
27677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2768bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgHandle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
2769af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    TypeHandleList* types,
27709faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    CodeHandleList* handlers,
27719faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Handle<Name> name,
27729faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    Code::StubType type,
27739faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    IcCheckType check) {
277440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  Label miss;
27759faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org
27769faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  if (check == PROPERTY) {
27779faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    GenerateNameCheck(name, this->name(), &miss);
27789faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  }
27799faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org
2780b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  Label number_case;
2781e3b442bc2783b64f4114011f9bbb0f1904d4b019palfia@homejinni.com  Register match = scratch1();
2782af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
2783e3b442bc2783b64f4114011f9bbb0f1904d4b019palfia@homejinni.com  __ JumpIfSmi(receiver(), smi_target, match);  // Reg match is 0 if Smi.
2784b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org
2785e3b442bc2783b64f4114011f9bbb0f1904d4b019palfia@homejinni.com  Register map_reg = scratch2();
2786c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2787af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  int receiver_count = types->length();
2788f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  int number_of_handled_maps = 0;
27899faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  __ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset));
279040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  for (int current = 0; current < receiver_count; ++current) {
2791af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    Handle<Type> type = types->at(current);
2792af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    Handle<Map> map = IC::TypeToMap(*type, isolate());
2793f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    if (!map->is_deprecated()) {
2794f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      number_of_handled_maps++;
2795e3b442bc2783b64f4114011f9bbb0f1904d4b019palfia@homejinni.com      // Check map and tail call if there's a match.
2796e3b442bc2783b64f4114011f9bbb0f1904d4b019palfia@homejinni.com      // Separate compare from branch, to provide path for above JumpIfSmi().
2797e3b442bc2783b64f4114011f9bbb0f1904d4b019palfia@homejinni.com      __ Subu(match, map_reg, Operand(map));
2798af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      if (type->Is(Type::Number())) {
2799b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org        ASSERT(!number_case.is_unused());
2800b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org        __ bind(&number_case);
2801b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org      }
2802f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      __ Jump(handlers->at(current), RelocInfo::CODE_TARGET,
2803e3b442bc2783b64f4114011f9bbb0f1904d4b019palfia@homejinni.com          eq, match, Operand(zero_reg));
2804f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org    }
280540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  }
2806f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org  ASSERT(number_of_handled_maps != 0);
2807c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2808c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&miss);
28092bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  TailCallBuiltin(masm(), MissBuiltin(kind()));
2810c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2811c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
28129faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  InlineCacheState state =
2813f005df6c3232e65028420519fbab7284bc9b33aedanno@chromium.org      number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC;
28149faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org  return GetICCode(kind(), type, name, state);
28157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
28167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
28177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
28186e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.comHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
28196e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    MapHandleList* receiver_maps,
28206e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    CodeHandleList* handler_stubs,
28216e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    MapHandleList* transitioned_maps) {
282240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  Label miss;
28234c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org  __ JumpIfSmi(receiver(), &miss);
282440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
282540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  int receiver_count = receiver_maps->length();
28264c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org  __ lw(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
2827b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  for (int i = 0; i < receiver_count; ++i) {
28286e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    if (transitioned_maps->at(i).is_null()) {
28296e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com      __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq,
28304c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org          scratch1(), Operand(receiver_maps->at(i)));
2831b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org    } else {
2832b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      Label next_map;
28334c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org      __ Branch(&next_map, ne, scratch1(), Operand(receiver_maps->at(i)));
28344c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org      __ li(transition_map(), Operand(transitioned_maps->at(i)));
28356e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com      __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET);
2836b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ bind(&next_map);
2837b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org    }
2838c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
2839c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2840c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&miss);
28412bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  TailCallBuiltin(masm(), MissBuiltin(kind()));
2842c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2843c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Return the generated code.
28442bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  return GetICCode(
28452bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org      kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
28465c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
28475c838251403b0be9a882540f1922577abba4c872ager@chromium.org
28485c838251403b0be9a882540f1922577abba4c872ager@chromium.org
284940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org#undef __
285040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org#define __ ACCESS_MASM(masm)
285140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
285240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
28536db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.orgvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
28546db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    MacroAssembler* masm) {
28556db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // ---------- S t a t e --------------
28566db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- ra     : return address
28576db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- a0     : key
28586db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- a1     : receiver
28596db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // -----------------------------------
2860af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  Label slow, miss;
28616db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
28626db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  Register key = a0;
28636db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  Register receiver = a1;
28646db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
2865af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  __ JumpIfNotSmi(key, &miss);
28666db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ lw(t0, FieldMemOperand(receiver, JSObject::kElementsOffset));
28676db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ sra(a2, a0, kSmiTagSize);
28686db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ LoadFromNumberDictionary(&slow, t0, a0, v0, a2, a3, t1);
28696db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ Ret();
28706db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
28716db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Slow case, key and receiver still in a0 and a1.
28726db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ bind(&slow);
28736db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ IncrementCounter(
28746db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org      masm->isolate()->counters()->keyed_load_external_array_slow(),
28756db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org      1, a2, a3);
28766db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Entry registers are intact.
28776db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // ---------- S t a t e --------------
28786db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- ra     : return address
28796db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- a0     : key
28806db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- a1     : receiver
28816db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // -----------------------------------
28822bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
28836db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
28846db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // Miss case, call the runtime.
2885af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  __ bind(&miss);
28866db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
28876db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // ---------- S t a t e --------------
28886db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- ra     : return address
28896db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- a0     : key
28906db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  //  -- a1     : receiver
28916db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  // -----------------------------------
2892af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
28936db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org}
28946db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
28956db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org
28965c838251403b0be9a882540f1922577abba4c872ager@chromium.org#undef __
28975c838251403b0be9a882540f1922577abba4c872ager@chromium.org
28985c838251403b0be9a882540f1922577abba4c872ager@chromium.org} }  // namespace v8::internal
28995c838251403b0be9a882540f1922577abba4c872ager@chromium.org
29009dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif  // V8_TARGET_ARCH_MIPS
2901