13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
23100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Redistribution and use in source and binary forms, with or without
33100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// modification, are permitted provided that the following conditions are
43100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// met:
53100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
63100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Redistributions of source code must retain the above copyright
73100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       notice, this list of conditions and the following disclaimer.
83100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Redistributions in binary form must reproduce the above
93100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       copyright notice, this list of conditions and the following
103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       disclaimer in the documentation and/or other materials provided
113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       with the distribution.
123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Neither the name of Google Inc. nor the names of its
133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       contributors may be used to endorse or promote products derived
143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       from this software without specific prior written permission.
153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "v8.h"
293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_MIPS)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "ic-inl.h"
33257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "codegen.h"
343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "stub-cache.h"
353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace v8 {
373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace internal {
383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define __ ACCESS_MASM(masm)
403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
42257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void ProbeTable(Isolate* isolate,
43257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       MacroAssembler* masm,
44257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       Code::Flags flags,
45257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       StubCache::Table table,
463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register receiver,
47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       Register name,
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       // Number of the cache entry, not scaled.
49257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       Register offset,
50257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       Register scratch,
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register scratch2,
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register offset_scratch) {
53257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
54257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference map_offset(isolate->stub_cache()->map_reference(table));
56257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
57257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address());
58257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address());
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint32_t map_off_addr = reinterpret_cast<uint32_t>(map_offset.address());
60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
61257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check the relative positions of the address fields.
62257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(value_off_addr > key_off_addr);
63257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT((value_off_addr - key_off_addr) % 4 == 0);
64257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT((value_off_addr - key_off_addr) < (256 * 4));
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(map_off_addr > key_off_addr);
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT((map_off_addr - key_off_addr) % 4 == 0);
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT((map_off_addr - key_off_addr) < (256 * 4));
68257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
69257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register base_addr = scratch;
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scratch = no_reg;
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Multiply by 3 because there are 3 fields per entry (name, code, map).
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(offset_scratch, offset, 1);
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(offset_scratch, offset_scratch, offset);
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Calculate the base address of the entry.
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(base_addr, Operand(key_offset));
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(at, offset_scratch, kPointerSizeLog2);
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(base_addr, base_addr, at);
81257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
82257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key in the entry matches the name.
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(at, MemOperand(base_addr, 0));
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&miss, ne, name, Operand(at));
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check the map matches.
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(at, MemOperand(base_addr, map_off_addr - key_off_addr));
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset));
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&miss, ne, at, Operand(scratch2));
90257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
91257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the code entry from the cache.
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register code = scratch2;
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scratch2 = no_reg;
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(code, MemOperand(base_addr, value_off_addr - key_off_addr));
95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the flags match what we're looking for.
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register flags_reg = base_addr;
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  base_addr = no_reg;
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(flags_reg, FieldMemOperand(code, Code::kFlagsOffset));
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(flags_reg, flags_reg, Operand(~Code::kFlagsNotUsedInLookup));
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&miss, ne, flags_reg, Operand(flags));
102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&miss);
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&miss);
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Jump to the first instruction in the code stub.
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag));
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(at);
114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Miss: fall through.
116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Helper function used to check that the dictionary doesn't contain
121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// the property. This function may return false negatives, so miss_label
122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// must always call a backup property check that is complete.
123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// This function is safe to call if the receiver has fast properties.
124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Name must be a symbol and receiver must be a heap object.
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* miss_label,
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register receiver,
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Handle<String> name,
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register scratch0,
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register scratch1) {
131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(name->IsSymbol());
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm->isolate()->counters();
133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kInterceptorOrAccessCheckNeededMask =
139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Bail out if the receiver has a named interceptor or requires access checks.
142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register map = scratch1;
143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(scratch0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(miss_label, ne, scratch0, Operand(zero_reg));
147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that receiver is a JSObject.
149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
1503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Branch(miss_label, lt, scratch0, Operand(FIRST_SPEC_OBJECT_TYPE));
151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load properties array.
153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register properties = scratch0;
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the properties array is a dictionary.
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset));
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register tmp = properties;
158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(miss_label, ne, map, Operand(tmp));
160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Restore the temporarily used register.
162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringDictionaryLookupStub::GenerateNegativeLookup(masm,
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     miss_label,
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     &done,
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     receiver,
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     properties,
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     name,
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     scratch1);
172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&done);
173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCache::GenerateProbe(MacroAssembler* masm,
1783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Code::Flags flags,
1793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Register receiver,
1803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Register name,
1813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                              Register scratch,
1823e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                              Register extra,
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register extra2,
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register extra3) {
185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Isolate* isolate = masm->isolate();
186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Make sure that code is valid. The multiplying code relies on the
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // entry size being 12.
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(sizeof(Entry) == 12);
191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Make sure the flags does not name a specific type.
193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Make sure that there are no register conflicts.
196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!scratch.is(receiver));
197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!scratch.is(name));
198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!extra.is(receiver));
199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!extra.is(name));
200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!extra.is(scratch));
201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!extra2.is(receiver));
202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!extra2.is(name));
203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!extra2.is(scratch));
204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!extra2.is(extra));
205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check register validity.
207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!scratch.is(no_reg));
208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!extra.is(no_reg));
209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!extra2.is(no_reg));
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!extra3.is(no_reg));
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Counters* counters = masm->isolate()->counters();
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1,
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      extra2, extra3);
215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the receiver isn't a smi.
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(receiver, &miss);
218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the map of the receiver and compute the hash.
220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(scratch, FieldMemOperand(name, String::kHashFieldOffset));
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(at, FieldMemOperand(receiver, HeapObject::kMapOffset));
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(scratch, scratch, at);
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint32_t mask = kPrimaryTableSize - 1;
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We shift out the last two bits because they are not part of the hash and
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // they are always 01 for maps.
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ srl(scratch, scratch, kHeapObjectTagSize);
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Xor(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask));
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(scratch, scratch, Operand(mask));
229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Probe the primary table.
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ProbeTable(isolate,
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             masm,
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             flags,
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             kPrimary,
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             receiver,
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             name,
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             scratch,
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             extra,
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             extra2,
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             extra3);
241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Primary miss: Compute hash for secondary probe.
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ srl(at, name, kHeapObjectTagSize);
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Subu(scratch, scratch, at);
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint32_t mask2 = kSecondaryTableSize - 1;
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask2));
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(scratch, scratch, Operand(mask2));
248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Probe the secondary table.
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ProbeTable(isolate,
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             masm,
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             flags,
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             kSecondary,
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             receiver,
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             name,
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             scratch,
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             extra,
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             extra2,
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             extra3);
260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Cache miss: Fall-through and let caller handle the miss by
262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // entering the runtime system.
263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1,
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      extra2, extra3);
2663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
2673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
2703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                                       int index,
2713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                                       Register prototype) {
272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the global or builtins object from the current context.
273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the global context from the global or builtins object.
275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(prototype,
276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset));
277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the function from the global context.
278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(prototype, MemOperand(prototype, Context::SlotOffset(index)));
279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the initial map.  The global functions all have initial maps.
280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(prototype,
281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the prototype from the initial map.
283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
2843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
2853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int index,
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register prototype,
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* miss) {
292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Isolate* isolate = masm->isolate();
293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check we're still in the same context.
294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!prototype.is(at));
296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ li(at, isolate->global());
297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(miss, ne, prototype, Operand(at));
298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the global function with the given index.
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSFunction> function(
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      JSFunction::cast(isolate->global_context()->get(index)));
301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load its initial map. The global functions all have initial maps.
302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ li(prototype, Handle<Map>(function->initial_map()));
303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the prototype from the initial map.
304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
30644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
30744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Load a fast property out of a holder object (src). In-object properties
3093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// are loaded directly otherwise the property is loaded from the properties
3103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// fixed array.
3113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Register dst,
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Register src,
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Handle<JSObject> holder,
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            int index) {
316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Adjust for the number of properties stored in the holder.
317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  index -= holder->map()->inobject_properties();
318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (index < 0) {
319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Get the property straight out of the holder.
320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int offset = holder->map()->instance_size() + (index * kPointerSize);
321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(dst, FieldMemOperand(src, offset));
322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Calculate the offset into the properties array.
324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int offset = index * kPointerSize + FixedArray::kHeaderSize;
325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(dst, FieldMemOperand(dst, offset));
327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
3293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
3323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           Register receiver,
3333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           Register scratch,
3343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           Label* miss_label) {
335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the receiver isn't a smi.
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(receiver, miss_label);
337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the object is a JS array.
339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ GetObjectType(receiver, scratch, scratch);
340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(miss_label, ne, scratch, Operand(JS_ARRAY_TYPE));
341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load length directly from the JS array.
343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Generate code to check if an object is a string.  If the object is a
349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// heap object, its map's instance type is left in the scratch1 register.
350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// If this is not needed, scratch1 and scratch2 may be the same register.
351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void GenerateStringCheck(MacroAssembler* masm,
352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register receiver,
353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register scratch1,
354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register scratch2,
355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Label* smi,
356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Label* non_string_object) {
357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the receiver isn't a smi.
358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(receiver, smi, t0);
359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the object is a string.
361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(scratch2, scratch1, Operand(kIsNotStringMask));
364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // The cast is to resolve the overload for the argument of 0x0.
365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(non_string_object,
366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            ne,
367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            scratch2,
368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Operand(static_cast<int32_t>(kStringTag)));
3693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
3703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
37244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Generate code to load the length from a string object and return the length.
37344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// If the receiver object is not a string or a wrapped string object the
37444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// execution continues at the miss label. The register containing the
37544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// receiver is potentially clobbered.
37644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
37744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            Register receiver,
37844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            Register scratch1,
37944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            Register scratch2,
38044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            Label* miss,
38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            bool support_wrappers) {
382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label check_wrapper;
383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check if the object is a string leaving the instance type in the
385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // scratch1 register.
386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateStringCheck(masm, receiver, scratch1, scratch2, miss,
387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      support_wrappers ? &check_wrapper : miss);
388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load length directly from the string.
390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(v0, FieldMemOperand(receiver, String::kLengthOffset));
391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (support_wrappers) {
394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check if the object is a JSValue wrapper.
395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&check_wrapper);
396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(miss, ne, scratch1, Operand(JS_VALUE_TYPE));
397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Unwrap the value and check if the wrapped value is a string.
399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset));
400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss);
401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(v0, FieldMemOperand(scratch1, String::kLengthOffset));
402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Ret();
403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
40444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
40544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
40644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
4083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                                 Register receiver,
4093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                                 Register scratch1,
4103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                                 Register scratch2,
4113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                                 Label* miss_label) {
412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(v0, scratch1);
414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
4153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
4163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
41844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Generate StoreField code, value is passed in a0 register.
4193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// After executing generated code, the receiver_reg and name_reg
4203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// may be clobbered.
4213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCompiler::GenerateStoreField(MacroAssembler* masm,
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<JSObject> object,
4233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                      int index,
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<Map> transition,
4253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                      Register receiver_reg,
4263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                      Register name_reg,
4273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                      Register scratch,
4283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                      Label* miss_label) {
429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0 : value.
430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label exit;
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the map of the object hasn't changed.
4328f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
4338f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch                                             : REQUIRE_EXACT_MAP;
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(receiver_reg, scratch, Handle<Map>(object->map()), miss_label,
4358f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch              DO_SMI_CHECK, mode);
436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Perform global security token check if needed.
438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (object->IsJSGlobalProxy()) {
439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Stub never generated for non-global objects that require access
443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // checks.
444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Perform map transition for the receiver if necessary.
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) {
448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The properties must be extended before we can store the value.
449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // We jump to a runtime call that extends the properties array.
450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ push(receiver_reg);
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(a2, Operand(transition));
452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Push(a2, a0);
453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ TailCallExternalReference(
454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                             masm->isolate()),
456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           3, 1);
457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return;
458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!transition.is_null()) {
461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Update the map of the object; no write barrier updating is
462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // needed because the map is never in new space.
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(t0, Operand(transition));
464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(t0, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Adjust for the number of properties stored in the object. Even in the
468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // face of a transition we can use the old map here because the size of the
469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // object and the number of in-object properties is not going to change.
470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  index -= object->map()->inobject_properties();
471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (index < 0) {
473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Set the property straight into the object.
474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int offset = object->map()->instance_size() + (index * kPointerSize);
475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(a0, FieldMemOperand(receiver_reg, offset));
476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Skip updating write barrier if storing a smi.
478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfSmi(a0, &exit, scratch);
479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Update the write barrier for the array address.
481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Pass the now unused name_reg as a scratch register.
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(name_reg, a0);
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(receiver_reg,
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        offset,
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        name_reg,
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch,
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kRAHasNotBeenSaved,
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs);
489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Write to the properties array.
491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int offset = index * kPointerSize + FixedArray::kHeaderSize;
492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Get the properties array.
493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(a0, FieldMemOperand(scratch, offset));
495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Skip updating write barrier if storing a smi.
497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfSmi(a0, &exit);
498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Update the write barrier for the array address.
500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Ok to clobber receiver_reg and name_reg, since we return.
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(name_reg, a0);
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(scratch,
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        offset,
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        name_reg,
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        receiver_reg,
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kRAHasNotBeenSaved,
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs);
508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the value (register v0).
511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&exit);
512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(v0, a0);
513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
5143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
5153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code = (kind == Code::LOAD_IC)
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? masm->isolate()->builtins()->LoadIC_Miss()
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : masm->isolate()->builtins()->KeyedLoadIC_Miss();
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(code, RelocInfo::CODE_TARGET);
523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void GenerateCallFunction(MacroAssembler* masm,
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Handle<Object> object,
528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 const ParameterCount& arguments,
5293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 Label* miss,
5303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 Code::ExtraICState extra_ic_state) {
531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0: receiver
533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1: function to call
534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the function really is a function.
536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(a1, miss);
537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ GetObjectType(a1, a3, a3);
538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE));
539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Patch the receiver on the stack with the global proxy if
541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // necessary.
542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (object->IsGlobalObject()) {
543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset));
544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(a3, MemOperand(sp, arguments.immediate() * kPointerSize));
545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Invoke the function.
5483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
5493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ? CALL_AS_FUNCTION
5503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : CALL_AS_METHOD;
5513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ InvokeFunction(a1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind);
552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void PushInterceptorArguments(MacroAssembler* masm,
556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register receiver,
557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register holder,
558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     Register name,
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<JSObject> holder_obj) {
560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(name);
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor));
563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register scratch = name;
5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(scratch, Operand(interceptor));
565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Push(scratch, receiver, holder);
566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset));
567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(scratch);
568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void CompileCallLoadPropertyWithInterceptor(
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register receiver,
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register holder,
5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register name,
5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder_obj) {
577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference ref =
580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          masm->isolate());
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ PrepareCEntryArgs(5);
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ PrepareCEntryFunction(ref);
584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CEntryStub stub(1);
586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CallStub(&stub);
587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const int kFastApiCallArguments = 3;
591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Reserves space for the extra arguments to FastHandleApiCall in the
594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// caller's frame.
595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//
596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// These arguments are set by CheckPrototypes and GenerateFastApiDirectCall.
597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void ReserveSpaceForFastApiCall(MacroAssembler* masm,
598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                       Register scratch) {
599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(Smi::FromInt(0) == 0);
600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < kFastApiCallArguments; i++) {
601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ push(zero_reg);
602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Undoes the effects of ReserveSpaceForFastApiCall.
607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void FreeSpaceForFastApiCall(MacroAssembler* masm) {
608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(kFastApiCallArguments);
6093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
6103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateFastApiDirectCall(MacroAssembler* masm,
613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      const CallOptimization& optimization,
614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                      int argc) {
615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[0]              : holder (set by CheckPrototypes)
6173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- sp[4]              : callee JS function
618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[8]              : call data
6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- sp[12]             : last JS argument
620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ...
6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- sp[(argc + 3) * 4] : first JS argument
622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[(argc + 4) * 4] : receiver
623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the function and setup the context.
6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSFunction> function = optimization.constant_function();
6263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(t1, function);
627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(cp, FieldMemOperand(t1, JSFunction::kContextOffset));
628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Pass the additional arguments FastHandleApiCall expects.
6303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
6313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> call_data(api_call_info->data());
6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (masm->isolate()->heap()->InNewSpace(*call_data)) {
6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(a0, api_call_info);
634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(t2, FieldMemOperand(a0, CallHandlerInfo::kDataOffset));
635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(t2, call_data);
637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store JS function and call data.
640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(t1, MemOperand(sp, 1 * kPointerSize));
641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(t2, MemOperand(sp, 2 * kPointerSize));
642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2 points to call data as expected by Arguments
644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // (refer to layout above).
645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(a2, sp, Operand(2 * kPointerSize));
646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kApiStackSpace = 4;
648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope frame_scope(masm, StackFrame::MANUAL);
650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ EnterExitFrame(false, kApiStackSpace);
651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // NOTE: the O32 abi requires a0 to hold a special pointer when returning a
653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // struct from the function (which is currently the case). This means we pass
654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the first argument in a1 instead of a0. TryCallApiFunctionAndReturn
655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // will handle setting up a0.
656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1 = v8::Arguments&
658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Arguments is built at sp + 1 (sp is a reserved spot for ra).
659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(a1, sp, kPointerSize);
660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // v8::Arguments::implicit_args = data
662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a2, MemOperand(a1, 0 * kPointerSize));
663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // v8::Arguments::values = last argument
664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(t0, a2, Operand(argc * kPointerSize));
665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(t0, MemOperand(a1, 1 * kPointerSize));
666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // v8::Arguments::length_ = argc
667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ li(t0, Operand(argc));
668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(t0, MemOperand(a1, 2 * kPointerSize));
669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // v8::Arguments::is_construct_call = 0
670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(zero_reg, MemOperand(a1, 3 * kPointerSize));
671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kStackUnwindSpace = argc + kFastApiCallArguments + 1;
6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address function_address = v8::ToCData<Address>(api_call_info->callback());
6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ApiFunction fun(function_address);
675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference ref =
676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ExternalReference(&fun,
677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ExternalReference::DIRECT_API_CALL,
678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        masm->isolate());
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AllowExternalCallThatCantCauseGC scope(masm);
6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallApiFunctionAndReturn(ref, kStackUnwindSpace);
681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
68344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass CallInterceptorCompiler BASE_EMBEDDED {
68444f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
68544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CallInterceptorCompiler(StubCompiler* stub_compiler,
68644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          const ParameterCount& arguments,
6873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Register name,
6883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                          Code::ExtraICState extra_ic_state)
68944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : stub_compiler_(stub_compiler),
69044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        arguments_(arguments),
6913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        name_(name),
6923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        extra_ic_state_(extra_ic_state) {}
69344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Compile(MacroAssembler* masm,
6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Handle<JSObject> object,
6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Handle<JSObject> holder,
6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Handle<String> name,
6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               LookupResult* lookup,
6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register receiver,
7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register scratch1,
7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register scratch2,
7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register scratch3,
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Label* miss) {
704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(holder->HasNamedInterceptor());
705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the receiver isn't a smi.
708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfSmi(receiver, miss);
709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CallOptimization optimization(lookup);
710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (optimization.is_constant_call()) {
7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       holder, lookup, name, optimization, miss);
713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
7143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     name, holder, miss);
716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
7203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CompileCacheable(MacroAssembler* masm,
7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Handle<JSObject> object,
7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register receiver,
7233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch1,
7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch2,
7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch3,
7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Handle<JSObject> interceptor_holder,
7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        LookupResult* lookup,
7283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Handle<String> name,
7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        const CallOptimization& optimization,
7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Label* miss_label) {
731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(optimization.is_constant_call());
732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(!lookup->holder()->IsGlobalObject());
733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Counters* counters = masm->isolate()->counters();
734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int depth1 = kInvalidProtoDepth;
735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int depth2 = kInvalidProtoDepth;
736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bool can_do_fast_api_call = false;
737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (optimization.is_simple_api_call() &&
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          !lookup->holder()->IsGlobalObject()) {
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      depth1 = optimization.GetPrototypeDepthOfExpectedType(
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          object, interceptor_holder);
741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (depth1 == kInvalidProtoDepth) {
7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        depth2 = optimization.GetPrototypeDepthOfExpectedType(
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            interceptor_holder, Handle<JSObject>(lookup->holder()));
744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      can_do_fast_api_call =
7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ IncrementCounter(counters->call_const_interceptor(), 1,
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch1, scratch2);
751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (can_do_fast_api_call) {
753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1,
754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          scratch1, scratch2);
755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ReserveSpaceForFastApiCall(masm, scratch1);
756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the maps from receiver to interceptor's holder
759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // haven't changed and thus we can invoke interceptor.
760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label miss_cleanup;
761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register holder =
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        scratch1, scratch2, scratch3,
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        name, depth1, miss);
766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Invoke an interceptor and if it provides a value,
768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // branch to |regular_invoke|.
769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label regular_invoke;
770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2,
771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        &regular_invoke);
772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Interceptor returned nothing for this property.  Try to use cached
774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // constant function.
775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the maps from interceptor's holder to constant function's
777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // holder haven't changed and thus we can use cached constant function.
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (*interceptor_holder != lookup->holder()) {
779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<JSObject>(lookup->holder()),
7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      scratch1, scratch2, scratch3,
7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      name, depth2, miss);
783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // CheckPrototypes has a side effect of fetching a 'holder'
785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // for API (object which is instanceof for the signature).  It's
786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // safe to omit it here, as if present, it should be fetched
787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // by the previous CheckPrototypes.
788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ASSERT(depth2 == kInvalidProtoDepth);
789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Invoke function.
792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (can_do_fast_api_call) {
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateFastApiDirectCall(masm, optimization, arguments_.immediate());
794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
7953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
7963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          ? CALL_AS_FUNCTION
7973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          : CALL_AS_METHOD;
798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ InvokeFunction(optimization.constant_function(), arguments_,
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        JUMP_FUNCTION, NullCallWrapper(), call_kind);
800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Deferred code for fast API call case---clean preallocated space.
803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (can_do_fast_api_call) {
804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ bind(&miss_cleanup);
805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FreeSpaceForFastApiCall(masm);
806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Branch(miss_label);
807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Invoke a regular function.
810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&regular_invoke);
811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (can_do_fast_api_call) {
812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FreeSpaceForFastApiCall(masm);
813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
81544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
81644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CompileRegular(MacroAssembler* masm,
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Handle<JSObject> object,
81844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Register receiver,
81944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Register scratch1,
82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Register scratch2,
82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Register scratch3,
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Handle<String> name,
8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Handle<JSObject> interceptor_holder,
82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                      Label* miss_label) {
825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register holder =
826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        scratch1, scratch2, scratch3,
8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        name, miss_label);
829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Call a runtime function to load the interceptor property.
8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Save the name_ register across the call.
833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ push(name_);
834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ CallExternalReference(
838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          ExternalReference(
839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              masm->isolate()),
841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          5);
842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Restore the name_ register.
843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ pop(name_);
8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Leave the internal frame.
84544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
84644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
84744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void LoadWithInterceptor(MacroAssembler* masm,
84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Register receiver,
84944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Register holder,
8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Handle<JSObject> holder_obj,
85144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Register scratch,
85244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Label* interceptor_succeeded) {
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FrameScope scope(masm, StackFrame::INTERNAL);
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Push(holder, name_);
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCallLoadPropertyWithInterceptor(masm,
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             receiver,
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder,
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             name_,
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder_obj);
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(name_);  // Restore the name.
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(receiver);  // Restore the holder.
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // If interceptor returns no-result sentinel, call the constant function.
866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(interceptor_succeeded, ne, v0, Operand(scratch));
86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
86944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  StubCompiler* stub_compiler_;
87144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const ParameterCount& arguments_;
87244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Register name_;
8733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Code::ExtraICState extra_ic_state_;
87444f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
87544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
87644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Generate code to check that a global property cell is empty. Create
879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// the property cell at compilation time if no cell exists for the
880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// property.
8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCell(MacroAssembler* masm,
8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<GlobalObject> global,
8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<String> name,
8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Register scratch,
8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Label* miss) {
8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSGlobalPropertyCell> cell =
8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GlobalObject::EnsurePropertyCell(global, name);
888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(cell->value()->IsTheHole());
8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(scratch, Operand(cell));
890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(scratch,
891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(miss, ne, scratch, Operand(at));
894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Calls GenerateCheckPropertyCell for each global object in the prototype chain
898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// from object to (but not including) holder.
8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCells(MacroAssembler* masm,
9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> object,
9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> holder,
9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<String> name,
9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register scratch,
9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Label* miss) {
9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> current = object;
9063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!current.is_identical_to(holder)) {
907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (current->IsGlobalObject()) {
9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateCheckPropertyCell(masm,
9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Handle<GlobalObject>::cast(current),
9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                name,
9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                scratch,
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                miss);
913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    current = Handle<JSObject>(JSObject::cast(current->GetPrototype()));
915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Convert and store int passed in register ival to IEEE 754 single precision
920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// floating point value at memory location (dst + 4 * wordoffset)
921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// If FPU is available use it for conversion.
922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void StoreIntAsFloat(MacroAssembler* masm,
923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register dst,
924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register wordoffset,
925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register ival,
926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register fval,
927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register scratch1,
928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register scratch2) {
929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (CpuFeatures::IsSupported(FPU)) {
930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CpuFeatures::Scope scope(FPU);
931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ mtc1(ival, f0);
932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cvt_s_w(f0, f0);
933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(scratch1, wordoffset, 2);
934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ addu(scratch1, dst, scratch1);
935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ swc1(f0, MemOperand(scratch1, 0));
936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // FPU is not available,  do manual conversions.
938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label not_special, done;
940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Move sign bit from source to destination.  This works because the sign
941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // bit in the exponent word of the double has the same position and polarity
942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // as the 2's complement sign bit in a Smi.
943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(kBinary32SignMask == 0x80000000u);
944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ And(fval, ival, Operand(kBinary32SignMask));
946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Negate value if it is negative.
947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ subu(scratch1, zero_reg, ival);
9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Movn(ival, scratch1, fval);
949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // We have -1, 0 or 1, which we treat specially. Register ival contains
951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // absolute value: it is either equal to 1 (special case of -1 and 1),
952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // greater than 1 (not a special case) or less than 1 (special case of 0).
953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&not_special, gt, ival, Operand(1));
954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // For 1 or -1 we need to or in the 0 exponent (biased).
956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    static const uint32_t exponent_word_for_1 =
957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        kBinary32ExponentBias << kBinary32ExponentShift;
958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Xor(scratch1, ival, Operand(1));
960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ li(scratch2, exponent_word_for_1);
961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ or_(scratch2, fval, scratch2);
9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Movz(fval, scratch2, scratch1);  // Only if ival is equal to 1.
963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&done);
964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&not_special);
966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Count leading zeros.
967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Gets the wrong answer for 0, but we already checked for that case above.
968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register zeros = scratch2;
9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Clz(zeros, ival);
970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Compute exponent and or it into the exponent register.
972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ li(scratch1, (kBitsPerInt - 1) + kBinary32ExponentBias);
973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ subu(scratch1, scratch1, zeros);
974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(scratch1, scratch1, kBinary32ExponentShift);
976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ or_(fval, fval, scratch1);
977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Shift up the source chopping the top bit off.
979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(zeros, zeros, Operand(1));
980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // This wouldn't work for 1 and -1 as the shift would be 32 which means 0.
981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sllv(ival, ival, zeros);
982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // And the top (top 20 bits).
983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ srl(scratch1, ival, kBitsPerInt - kBinary32MantissaBits);
984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ or_(fval, fval, scratch1);
985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&done);
987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(scratch1, wordoffset, 2);
989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ addu(scratch1, dst, scratch1);
990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(fval, MemOperand(scratch1, 0));
991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Convert unsigned integer with specified number of leading zeroes in binary
996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// representation to IEEE 754 double.
997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Integer to convert is passed in register hiword.
998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Resulting double is returned in registers hiword:loword.
999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// This functions does not work correctly for 0.
1000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void GenerateUInt2Double(MacroAssembler* masm,
1001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register hiword,
1002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register loword,
1003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Register scratch,
1004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                int leading_zeroes) {
1005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int meaningful_bits = kBitsPerInt - leading_zeroes - 1;
1006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int biased_exponent = HeapNumber::kExponentBias + meaningful_bits;
1007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int mantissa_shift_for_hi_word =
1009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      meaningful_bits - HeapNumber::kMantissaBitsInTopWord;
1010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int mantissa_shift_for_lo_word =
1012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      kBitsPerInt - mantissa_shift_for_hi_word;
1013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ li(scratch, biased_exponent << HeapNumber::kExponentShift);
1015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (mantissa_shift_for_hi_word > 0) {
1016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(loword, hiword, mantissa_shift_for_lo_word);
1017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ srl(hiword, hiword, mantissa_shift_for_hi_word);
1018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ or_(hiword, scratch, hiword);
1019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ mov(loword, zero_reg);
1021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(hiword, hiword, mantissa_shift_for_hi_word);
1022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ or_(hiword, scratch, hiword);
1023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If least significant bit of biased exponent was not 1 it was corrupted
1026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // by most significant bit of mantissa so we should fix that.
1027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!(biased_exponent & 1)) {
1028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ li(scratch, 1 << HeapNumber::kExponentShift);
1029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ nor(scratch, scratch, scratch);
1030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ and_(hiword, hiword, scratch);
1031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef __
10363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define __ ACCESS_MASM(masm())
10373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10393ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister StubCompiler::CheckPrototypes(Handle<JSObject> object,
104044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Register object_reg,
10413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> holder,
104244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Register holder_reg,
104344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Register scratch1,
104444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Register scratch2,
10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<String> name,
104644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       int save_at_depth,
104744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Label* miss) {
1048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Make sure there's no overlap between holder and object registers.
1049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
1050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         && !scratch2.is(scratch1));
1052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Keep track of the current object in register reg.
1054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register reg = object_reg;
1055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int depth = 0;
1056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (save_at_depth == depth) {
1058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(reg, MemOperand(sp));
1059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check the maps in the prototype chain.
1062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Traverse the prototype chain from the object and do map checks.
10633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> current = object;
10643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!current.is_identical_to(holder)) {
10653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ++depth;
1066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Only global objects and objects that do not require access
1068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // checks are allowed in stubs.
1069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
1070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> prototype(JSObject::cast(current->GetPrototype()));
1072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!current->HasFastProperties() &&
1073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        !current->IsJSGlobalObject() &&
1074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        !current->IsJSGlobalProxy()) {
1075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (!name->IsSymbol()) {
10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        name = factory()->LookupSymbol(name);
1077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(current->property_dictionary()->FindEntry(*name) ==
1079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             StringDictionary::kNotFound);
1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       scratch1, scratch2);
1083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
10853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reg = holder_reg;  // From now on the object will be in holder_reg.
1086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Map> current_map(current->map());
10893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK,
10903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  ALLOW_ELEMENT_TRANSITION_MAPS);
10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check access rights to the global object.  This has to happen after
10923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the map check so that we know that the object is actually a global
10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // object.
1094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (current->IsJSGlobalProxy()) {
10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckAccessGlobalProxy(reg, scratch2, miss);
1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
10973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reg = holder_reg;  // From now on the object will be in holder_reg.
1098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (heap()->InNewSpace(*prototype)) {
11003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The prototype is in new space; we cannot store a reference to it
11013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // in the code.  Load it from the map.
11023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
11043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The prototype is in old space; load it directly.
11053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ li(reg, Operand(prototype));
1106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (save_at_depth == depth) {
1110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(reg, MemOperand(sp));
1111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Go to the next object in the prototype chain.
1114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    current = prototype;
1115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
111785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Log the check depth.
111885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1));
11193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check the holder map.
11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(reg, scratch1, Handle<Map>(current->map()), miss,
11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Perform security check for access to the global object.
1125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
1126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (holder->IsJSGlobalProxy()) {
1127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ CheckAccessGlobalProxy(reg, scratch1, miss);
11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If we've skipped any global objects, it's not enough to verify that
11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // their maps haven't changed.  We also need to check that the property
11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // cell for the property is still empty.
11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
1134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the register containing the holder.
1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return reg;
113744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
113844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
113944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadField(Handle<JSObject> object,
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<JSObject> holder,
11423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                     Register receiver,
11433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                     Register scratch1,
11443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                     Register scratch2,
114544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                     Register scratch3,
11463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                     int index,
11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<String> name,
11483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                     Label* miss) {
1149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the receiver isn't a smi.
11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(receiver, miss);
1151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the maps haven't changed.
11533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = CheckPrototypes(
11543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateFastPropertyLoad(masm(), v0, reg, holder, index);
1156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
11573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
11583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSObject> holder,
11623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                        Register receiver,
11633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                        Register scratch1,
11643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                        Register scratch2,
116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Register scratch3,
11663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSFunction> value,
11673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<String> name,
11683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                        Label* miss) {
1169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the receiver isn't a smi.
1170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(receiver, miss, scratch1);
1171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the maps haven't changed.
11737a930e02c0b52d70d022ed255db551895dfe1157Ben Murdoch  CheckPrototypes(object, receiver, holder,
11747a930e02c0b52d70d022ed255db551895dfe1157Ben Murdoch                  scratch1, scratch2, scratch3, name, miss);
1175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the constant value.
11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(v0, value);
1178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
11793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
11803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
11833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSObject> holder,
11843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register receiver,
11853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register name_reg,
11863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch1,
11873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch2,
11883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch3,
11893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<AccessorInfo> callback,
11903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<String> name,
11913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Label* miss) {
1192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the receiver isn't a smi.
1193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(receiver, miss, scratch1);
1194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the maps haven't changed.
11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = CheckPrototypes(object, receiver, holder, scratch1,
11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch2, scratch3, name, miss);
1198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Build AccessorInfo::args_ list on the stack and push property name below
1200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the exit frame to make GC aware of them and store pointers to them.
1201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(receiver);
1202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(scratch2, sp);  // scratch2 = AccessorInfo::args_
12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (heap()->InNewSpace(callback->data())) {
12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(scratch3, callback);
1205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset));
1206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(scratch3, Handle<Object>(callback->data()));
1208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Push(reg, scratch3, name_reg);
1210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(a2, scratch2);  // Saved in case scratch2 == a1.
1211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(a1, sp);  // a1 (first argument - see note below) = Handle<String>
1212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // NOTE: the O32 abi requires a0 to hold a special pointer when returning a
1214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // struct from the function (which is currently the case). This means we pass
1215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the arguments in a1-a2 instead of a0-a1. TryCallApiFunctionAndReturn
1216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // will handle setting up a0.
1217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kApiStackSpace = 1;
12193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope frame_scope(masm(), StackFrame::MANUAL);
122085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  __ EnterExitFrame(false, kApiStackSpace);
12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Create AccessorInfo instance on the stack above the exit frame with
12233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // scratch2 (internal::Object** args_) as the data.
1224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a2, MemOperand(sp, kPointerSize));
1225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2 (second argument - see note above) = AccessorInfo&
1226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(a2, sp, kPointerSize);
1227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
12283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int kStackUnwindSpace = 4;
12293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address getter_address = v8::ToCData<Address>(callback->getter());
12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ApiFunction fun(getter_address);
1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference ref =
1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ExternalReference(&fun,
1233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ExternalReference::DIRECT_GETTER_CALL,
1234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        masm()->isolate());
12353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallApiFunctionAndReturn(ref, kStackUnwindSpace);
12363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
12373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Handle<JSObject> interceptor_holder,
12413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           LookupResult* lookup,
12423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           Register receiver,
12433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           Register name_reg,
12443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           Register scratch1,
12453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           Register scratch2,
124644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                           Register scratch3,
12473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Handle<String> name,
12483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                           Label* miss) {
1249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(interceptor_holder->HasNamedInterceptor());
1250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the receiver isn't a smi.
1253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(receiver, miss);
1254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // So far the most popular follow ups for interceptor loads are FIELD
1256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // and CALLBACKS, so inline only them, other cases may be added
1257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // later.
1258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool compile_followup_inline = false;
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (lookup->IsFound() && lookup->IsCacheable()) {
1260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (lookup->type() == FIELD) {
1261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      compile_followup_inline = true;
1262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else if (lookup->type() == CALLBACKS &&
12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        lookup->GetCallbackObject()->IsAccessorInfo()) {
12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      compile_followup_inline =
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL;
1266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (compile_followup_inline) {
1270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Compile the interceptor call, followed by inline code to load the
1271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // property from further up the prototype chain if the call fails.
1272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the maps haven't changed.
1273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
1274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          scratch1, scratch2, scratch3,
1275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          name, miss);
1276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
1277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Save necessary data before invoking an interceptor.
1279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Requires a frame to make GC aware of pushed pointers.
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FrameScope frame_scope(masm(), StackFrame::INTERNAL);
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // CALLBACKS case needs a receiver to be passed into C++ callback.
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Push(receiver, holder_reg, name_reg);
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Push(holder_reg, name_reg);
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Invoke an interceptor.  Note: map checks from receiver to
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // interceptor's holder has been compiled before (see a caller
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // of this method).
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCallLoadPropertyWithInterceptor(masm(),
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             receiver,
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder_reg,
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             name_reg,
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             interceptor_holder);
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if interceptor provided a value for property.  If it's
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the case, return immediately.
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label interceptor_failed;
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex);
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&interceptor_failed, eq, v0, Operand(scratch1));
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      frame_scope.GenerateLeaveFrame();
13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Ret();
130385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&interceptor_failed);
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(name_reg);
13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(holder_reg);
13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ pop(receiver);
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Leave the internal frame.
131185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    }
1312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the maps from interceptor's holder to lookup's holder
1313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // haven't changed.  And load lookup's holder into |holder| register.
13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (*interceptor_holder != lookup->holder()) {
1315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      holder_reg = CheckPrototypes(interceptor_holder,
1316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   holder_reg,
13173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Handle<JSObject>(lookup->holder()),
1318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   scratch1,
1319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   scratch2,
1320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   scratch3,
1321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   name,
1322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                   miss);
1323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (lookup->type() == FIELD) {
1326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // We found FIELD property in prototype chain of interceptor's holder.
1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Retrieve a field from field's holder.
1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      GenerateFastPropertyLoad(masm(), v0, holder_reg,
13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Handle<JSObject>(lookup->holder()),
13303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               lookup->GetFieldIndex());
1331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
1332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
1333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // We found CALLBACKS property in prototype chain of interceptor's
1334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // holder.
1335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ASSERT(lookup->type() == CALLBACKS);
13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<AccessorInfo> callback(
13373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject()));
1338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ASSERT(callback->getter() != NULL);
1339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Tail call to runtime.
1341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Important invariant in CALLBACKS case: the code above must be
1342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // structured to never clobber |receiver| register.
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ li(scratch2, callback);
1344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // holder_reg is either receiver or scratch1.
1345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (!receiver.is(holder_reg)) {
1346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        ASSERT(scratch1.is(holder_reg));
1347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Push(receiver, holder_reg);
1348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ lw(scratch3,
1349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              FieldMemOperand(scratch2, AccessorInfo::kDataOffset));
1350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Push(scratch3, scratch2, name_reg);
1351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
1352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ push(receiver);
1353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ lw(scratch3,
1354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              FieldMemOperand(scratch2, AccessorInfo::kDataOffset));
1355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Push(holder_reg, scratch3, scratch2, name_reg);
1356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
1357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ExternalReference ref =
1359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
1360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            masm()->isolate());
1361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ TailCallExternalReference(ref, 5, 1);
1362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {  // !compile_followup_inline
1364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Call the runtime system to load the interceptor.
1365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the maps haven't changed.
1366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
1367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          scratch1, scratch2, scratch3,
1368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                          name, miss);
1369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    PushInterceptorArguments(masm(), receiver, holder_reg,
1370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                             name_reg, interceptor_holder);
1371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ExternalReference ref = ExternalReference(
1373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), masm()->isolate());
1374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ TailCallExternalReference(ref, 5, 1);
1375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
13763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
13773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
1380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::KEYED_CALL_IC) {
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(miss, ne, a2, Operand(name));
1382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
138344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
13846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
138944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   Label* miss) {
1390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(holder->IsGlobalObject());
1391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the number of arguments.
1393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int argc = arguments().immediate();
1394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the receiver from the stack.
1396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a0, MemOperand(sp, argc * kPointerSize));
1397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the maps haven't changed.
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(a0, miss);
1400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CheckPrototypes(object, a0, holder, a3, a1, t0, name, miss);
14013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
14023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
14033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
14043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell(
14053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* miss) {
1408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the value from the cell.
14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a3, Operand(cell));
1410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a1, FieldMemOperand(a3, JSGlobalPropertyCell::kValueOffset));
1411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the cell contains the same function.
14133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (heap()->InNewSpace(*function)) {
1414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // We can't embed a pointer to a function in new space so we have
1415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // to verify that the shared function info is unchanged. This has
1416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // the nice side effect that multiple closures based on the same
1417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // function can all use this call IC. Before we load through the
1418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // function, we have to verify that it still is a function.
1419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfSmi(a1, miss);
1420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ GetObjectType(a1, a3, a3);
1421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE));
1422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check the shared function info. Make sure it hasn't changed.
1424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ li(a3, Handle<SharedFunctionInfo>(function->shared()));
1425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(miss, ne, t0, Operand(a3));
1427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(miss, ne, a1, Operand(function));
1429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
14303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
14313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
14323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() {
14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code =
1435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                               kind_,
14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               extra_state_);
14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(code, RelocInfo::CODE_TARGET);
14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
14433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
144444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                int index,
14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
1446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
1448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
1449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
1450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
1451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateNameCheck(name, &miss);
1453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int argc = arguments().immediate();
1455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the receiver of the function from the stack into a0.
1457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a0, MemOperand(sp, argc * kPointerSize));
1458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the receiver isn't a smi.
1459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(a0, &miss, t0);
1460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Do the right check and compute the holder register.
1462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register reg = CheckPrototypes(object, a0, holder, a1, a3, t0, name, &miss);
1463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateFastPropertyLoad(masm(), a1, reg, holder, index);
1464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
1466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle call cache miss.
1468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
1472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(FIELD, name);
14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall(
14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
1484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
1486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ...
1487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[argc * 4]           : receiver
1488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
14893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If object is not an array, bail out to regular call.
14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
14923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
14943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateNameCheck(name, &miss);
14963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register receiver = a1;
1498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the receiver from the stack.
1500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int argc = arguments().immediate();
1501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(receiver, MemOperand(sp, argc * kPointerSize));
1502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the receiver isn't a smi.
1504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(receiver, &miss);
1505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the maps haven't changed.
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, a3, v0, t0,
15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, &miss);
1509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (argc == 0) {
1511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Nothing to do, just return the length.
1512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
1513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Drop(argc + 1);
1514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Ret();
1515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label call_builtin;
15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (argc == 1) {  // Otherwise fall through to call the builtin.
15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label attempt_to_grow_elements;
1519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register elements = t2;
15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register end_elements = t1;
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements array of the object.
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
152485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check that the elements are in fast mode and writable.
15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckMap(elements,
15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  v0,
15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Heap::kFixedArrayMapRootIndex,
15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  &call_builtin,
15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  DONT_DO_SMI_CHECK);
15315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
1532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Get the array's length into v0 and calculate new length.
1533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
1534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      STATIC_ASSERT(kSmiTagSize == 1);
1535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      STATIC_ASSERT(kSmiTag == 0);
1536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Addu(v0, v0, Operand(Smi::FromInt(argc)));
1537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements' length.
1539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset));
1540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Check if we could survive without allocation.
1542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Branch(&attempt_to_grow_elements, gt, v0, Operand(t0));
1543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if value is a smi.
15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label with_write_barrier;
15463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize));
15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfNotSmi(t0, &with_write_barrier);
15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Save new length.
1550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
1551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
1553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // We may need a register containing the address end_elements below,
1554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // so write back the value in end_elements.
1555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize);
1556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Addu(end_elements, elements, end_elements);
1557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      const int kEndElementsOffset =
1558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(end_elements, end_elements, kEndElementsOffset);
15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(t0, MemOperand(end_elements));
1561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Check for a smi.
1563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Drop(argc + 1);
1564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
1565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ bind(&with_write_barrier);
15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(a3, FieldMemOperand(receiver, HeapObject::kMapOffset));
15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_smi_only_arrays  && !FLAG_trace_elements_transitions) {
15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label fast_object, not_fast_object;
15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(a3, t3, &not_fast_object);
15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&fast_object);
15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // In case of fast smi-only, convert to fast object, otherwise bail out.
15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&not_fast_object);
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastSmiOnlyElements(a3, t3, &call_builtin);
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // edx: receiver
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // r3: map
15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               FAST_ELEMENTS,
15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               a3,
15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               t3,
15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               &call_builtin);
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(a2, receiver);
15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm());
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&fast_object);
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(a3, a3, &call_builtin);
15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Save new length.
15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // We may need a register containing the address end_elements below,
15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // so write back the value in end_elements.
15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize);
15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(end_elements, elements, end_elements);
15993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(end_elements, end_elements, kEndElementsOffset);
16003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(t0, MemOperand(end_elements));
16013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWrite(elements,
16033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     end_elements,
16043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     t0,
16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     kRAHasNotBeenSaved,
16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     kDontSaveFPRegs,
16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     EMIT_REMEMBERED_SET,
16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     OMIT_SMI_CHECK);
1609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Drop(argc + 1);
1610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
1611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ bind(&attempt_to_grow_elements);
1613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // v0: array's length + 1.
1614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // t0: elements' length.
1615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (!FLAG_inline_new) {
1617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&call_builtin);
1618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
1619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(a2, MemOperand(sp, (argc - 1) * kPointerSize));
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Growing elements that are SMI-only requires special handling in case
16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the new element is non-Smi. For now, delegate to the builtin.
16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label no_fast_elements_check;
16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfSmi(a2, &no_fast_elements_check);
16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset));
16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckFastObjectElements(t3, t3, &call_builtin);
16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&no_fast_elements_check);
16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ExternalReference new_space_allocation_top =
1630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          ExternalReference::new_space_allocation_top_address(
1631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              masm()->isolate());
1632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ExternalReference new_space_allocation_limit =
1633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          ExternalReference::new_space_allocation_limit_address(
1634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              masm()->isolate());
1635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      const int kAllocationDelta = 4;
1637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Load top and check if it is the end of elements.
1638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize);
1639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Addu(end_elements, elements, end_elements);
1640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Addu(end_elements, end_elements, Operand(kEndElementsOffset));
1641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ li(t3, Operand(new_space_allocation_top));
16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(a3, MemOperand(t3));
16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&call_builtin, ne, end_elements, Operand(a3));
1644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ li(t5, Operand(new_space_allocation_limit));
1646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ lw(t5, MemOperand(t5));
16473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(a3, a3, Operand(kAllocationDelta * kPointerSize));
16483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&call_builtin, hi, a3, Operand(t5));
1649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // We fit and could grow elements.
1651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Update new_space_allocation_top.
16523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(a3, MemOperand(t3));
1653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Push the argument.
16543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(a2, MemOperand(end_elements));
1655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Fill the rest with holes.
16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(a3, Heap::kTheHoleValueRootIndex);
1657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      for (int i = 1; i < kAllocationDelta; i++) {
16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sw(a3, MemOperand(end_elements, i * kPointerSize));
1659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
1660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Update elements' and array's sizes.
1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
1663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta)));
1664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset));
1665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Elements are in new space, so write barrier is not required.
1667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Drop(argc + 1);
1668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
1669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&call_builtin);
1671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
1672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                   masm()->isolate()),
1673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 argc + 1,
1674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 1);
1675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle call cache miss.
1678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
16793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
1682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(function);
1683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
16863ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall(
16873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
16883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
16893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
16903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
16913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
1694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
1695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
1696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ...
1697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[argc * 4]           : receiver
1698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
1699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If object is not an array, bail out to regular call.
17013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
1702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss, return_undefined, call_builtin;
1704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register receiver = a1;
1705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register elements = a3;
1706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateNameCheck(name, &miss);
1707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the receiver from the stack.
1709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int argc = arguments().immediate();
1710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(receiver, MemOperand(sp, argc * kPointerSize));
1711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the receiver isn't a smi.
1712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(receiver, &miss);
1713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the maps haven't changed.
17153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, elements,
17163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  t0, v0, name, &miss);
1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array of the object.
1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
1720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the elements are in fast mode and writable.
1722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(elements,
1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              v0,
1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              Heap::kFixedArrayMapRootIndex,
1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              &call_builtin,
1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              DONT_DO_SMI_CHECK);
1727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the array's length into t0 and calculate new length.
1729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset));
1730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Subu(t0, t0, Operand(Smi::FromInt(1)));
1731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&return_undefined, lt, t0, Operand(zero_reg));
1732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the last element.
1734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(t2, Heap::kTheHoleValueRootIndex);
1735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(kSmiTagSize == 1);
1736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
1737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We can't address the last element in one operation. Compute the more
1738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // expensive shift first, and use an offset later on.
1739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(t1, t0, kPointerSizeLog2 - kSmiTagSize);
1740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(elements, elements, t1);
1741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(v0, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag));
1742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&call_builtin, eq, v0, Operand(t2));
1743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Set the array's length.
1745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset));
1746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Fill with the hole.
1748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(t2, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag));
1749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(argc + 1);
1750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
1751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&return_undefined);
1753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
1754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(argc + 1);
1755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
1756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&call_builtin);
1758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop,
1759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                 masm()->isolate()),
1760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               argc + 1,
1761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               1);
1762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle call cache miss.
1764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
17653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
1768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(function);
1769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
17733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
17743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
17763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
17773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2                     : function name
1780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra                     : return address
1781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
1782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ...
1783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[argc * 4]           : receiver
1784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
1785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If object is not a string, bail out to regular call.
17873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
1788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int argc = arguments().immediate();
1790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
1791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label name_miss;
1792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label index_out_of_range;
1793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
1795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
17973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    index_out_of_range_label = &miss;
1800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateNameCheck(name, &name_miss);
1803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the maps starting from the prototype haven't changed.
1805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateDirectLoadGlobalFunctionPrototype(masm(),
1806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Context::STRING_FUNCTION_INDEX,
1807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            v0,
1808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            &miss);
18093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
18103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
18113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  v0, holder, a1, a3, t0, name, &miss);
1812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register receiver = a1;
1814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register index = t1;
1815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register result = v0;
1816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(receiver, MemOperand(sp, argc * kPointerSize));
1817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (argc > 0) {
1818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize));
1819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
1821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharCodeAtGenerator generator(receiver,
18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index,
18253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      result,
18263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a string.
18273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a number.
18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index_out_of_range_label,
18293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      STRING_INDEX_IS_NUMBER);
18303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
1831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(argc + 1);
1832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
1833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  StubRuntimeCallHelper call_helper;
18353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
1836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (index_out_of_range.is_linked()) {
1838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&index_out_of_range);
1839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(v0, Heap::kNanValueRootIndex);
1840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Drop(argc + 1);
1841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Ret();
1842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
1845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Restore function name in a2.
18463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a2, name);
1847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&name_miss);
18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
1851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(function);
18523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
18533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
18543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall(
18563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
18573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
18583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
18593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2                     : function name
1863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra                     : return address
1864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
1865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ...
1866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[argc * 4]           : receiver
1867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
1868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If object is not a string, bail out to regular call.
18703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
1871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int argc = arguments().immediate();
1873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
1874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label name_miss;
1875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label index_out_of_range;
1876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
1877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
18783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    index_out_of_range_label = &miss;
1881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateNameCheck(name, &name_miss);
1883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the maps starting from the prototype haven't changed.
1885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateDirectLoadGlobalFunctionPrototype(masm(),
1886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            Context::STRING_FUNCTION_INDEX,
1887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            v0,
1888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                            &miss);
18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
18903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
18913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  v0, holder, a1, a3, t0, name, &miss);
1892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register receiver = v0;
1894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register index = t1;
18953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = a3;
1896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register result = v0;
1897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(receiver, MemOperand(sp, argc * kPointerSize));
1898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (argc > 0) {
1899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize));
1900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
1902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
19043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharAtGenerator generator(receiver,
19053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index,
19063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  scratch,
19073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  result,
19083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a string.
19093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a number.
19103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index_out_of_range_label,
19113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  STRING_INDEX_IS_NUMBER);
19123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
1913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(argc + 1);
1914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
1915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  StubRuntimeCallHelper call_helper;
19173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
1918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (index_out_of_range.is_linked()) {
1920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&index_out_of_range);
1921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(v0, Heap::kEmptyStringRootIndex);
1922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Drop(argc + 1);
1923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Ret();
1924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
1927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Restore function name in a2.
19283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a2, name);
1929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&name_miss);
19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
1933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(function);
19343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
19353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
19363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
19373ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
19383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
19393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
19403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
19413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
19423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2                     : function name
1945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra                     : return address
1946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
1947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ...
1948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[argc * 4]           : receiver
1949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
1950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int argc = arguments().immediate();
1952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If the object is not a JSObject or we got an unexpected number of
1954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // arguments, bail out to the regular call.
19553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
1956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
1958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateNameCheck(name, &miss);
1959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
19603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
1961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a1, MemOperand(sp, 1 * kPointerSize));
1962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    STATIC_ASSERT(kSmiTag == 0);
1964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfSmi(a1, &miss);
1965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, v0, a3, t0,
19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
1968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
19693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
19703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
19713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
1972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    GenerateLoadFunctionFromCell(cell, function, &miss);
1973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the char code argument.
1976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register code = a1;
1977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(code, MemOperand(sp, 0 * kPointerSize));
1978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check the code is a smi.
1980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label slow;
1981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
1982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(code, &slow);
1983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Convert the smi code to uint16.
1985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(code, code, Operand(Smi::FromInt(0xffff)));
1986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
19873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharFromCodeGenerator generator(code, v0);
19883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
1989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(argc + 1);
1990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
1991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  StubRuntimeCallHelper call_helper;
19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
1994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Tail call the full function. We do not have to patch the receiver
1996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // because the function makes no use of it.
1997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&slow);
19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(
19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
2000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2: function name.
20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
20073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
20083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
20103ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall(
20113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
20123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
20133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2                     : function name
2018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra                     : return address
2019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
2020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ...
2021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[argc * 4]           : receiver
2022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!CpuFeatures::IsSupported(FPU)) {
20253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
20263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
202785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
20283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CpuFeatures::Scope scope_fpu(FPU);
2029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int argc = arguments().immediate();
2030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If the object is not a JSObject or we got an unexpected number of
2031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // arguments, bail out to the regular call.
20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss, slow;
2035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateNameCheck(name, &miss);
2036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
2038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a1, MemOperand(sp, 1 * kPointerSize));
2039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    STATIC_ASSERT(kSmiTag == 0);
2040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfSmi(a1, &miss);
20413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0,
20423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
2043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
20443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
20453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
20463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
2047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    GenerateLoadFunctionFromCell(cell, function, &miss);
2048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the (only) argument into v0.
2051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(v0, MemOperand(sp, 0 * kPointerSize));
2052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If the argument is a smi, just return.
2054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
2055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(t0, v0, Operand(kSmiTagMask));
2056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(argc + 1, eq, t0, Operand(zero_reg));
2057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret(eq, t0, Operand(zero_reg));
2058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
2060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label wont_fit_smi, no_fpu_error, restore_fcsr_and_return;
2062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If fpu is enabled, we use the floor instruction.
2064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the HeapNumber value.
2066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset));
2067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Backup FCSR.
2069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cfc1(a3, FCSR);
2070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Clearing FCSR clears the exception mask with no side-effects.
2071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ctc1(zero_reg, FCSR);
2072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Convert the argument to an integer.
2073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ floor_w_d(f0, f0);
2074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Start checking for special cases.
2076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the argument exponent and clear the sign bit.
2077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(t1, FieldMemOperand(v0, HeapNumber::kValueOffset + kPointerSize));
2078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(t2, t1, Operand(~HeapNumber::kSignMask));
2079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ srl(t2, t2, HeapNumber::kMantissaBitsInTopWord);
2080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Retrieve FCSR and check for fpu errors.
2082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cfc1(t5, FCSR);
20833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ And(t5, t5, Operand(kFCSRExceptionFlagMask));
2084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&no_fpu_error, eq, t5, Operand(zero_reg));
2085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for NaN, Infinity, and -Infinity.
2087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // They are invariant through a Math.Floor call, so just
2088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // return the original argument.
2089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Subu(t3, t2, Operand(HeapNumber::kExponentMask
2090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        >> HeapNumber::kMantissaBitsInTopWord));
2091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&restore_fcsr_and_return, eq, t3, Operand(zero_reg));
2092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We had an overflow or underflow in the conversion. Check if we
2093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have a big exponent.
2094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If greater or equal, the argument is already round and in v0.
2095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&restore_fcsr_and_return, ge, t3,
2096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Operand(HeapNumber::kMantissaBits));
2097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&wont_fit_smi);
2098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&no_fpu_error);
2100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Move the result back to v0.
2101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mfc1(v0, f0);
2102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check if the result fits into a smi.
2103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(a1, v0, Operand(0x40000000));
2104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&wont_fit_smi, lt, a1, Operand(zero_reg));
2105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Tag the result.
2106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
2107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(v0, v0, kSmiTagSize);
2108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for -0.
2110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&restore_fcsr_and_return, ne, v0, Operand(zero_reg));
2111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t1 already holds the HeapNumber exponent.
2112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(t0, t1, Operand(HeapNumber::kSignMask));
2113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If our HeapNumber is negative it was -0, so load its address and return.
2114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Else v0 is loaded with 0, so we can also just return.
2115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&restore_fcsr_and_return, eq, t0, Operand(zero_reg));
2116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(v0, MemOperand(sp, 0 * kPointerSize));
2117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&restore_fcsr_and_return);
2119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Restore FCSR and return.
2120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ctc1(a3, FCSR);
2121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(argc + 1);
2123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
2124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&wont_fit_smi);
2126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Restore FCSR and fall to slow case.
2127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ctc1(a3, FCSR);
2128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&slow);
2130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Tail call the full function. We do not have to patch the receiver
2131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // because the function makes no use of it.
21323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(
21333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
2134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2: function name.
21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
21403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
21413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
21423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
21433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
21443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall(
21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
21463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
21473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
21483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
21493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2                     : function name
2152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra                     : return address
2153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
2154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ...
2155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[argc * 4]           : receiver
2156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int argc = arguments().immediate();
2159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If the object is not a JSObject or we got an unexpected number of
2160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // arguments, bail out to the regular call.
21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
216485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
21653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateNameCheck(name, &miss);
21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
2167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a1, MemOperand(sp, 1 * kPointerSize));
2168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    STATIC_ASSERT(kSmiTag == 0);
2169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfSmi(a1, &miss);
21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, v0, a3, t0,
21713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
2172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
21743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
21753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
2176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    GenerateLoadFunctionFromCell(cell, function, &miss);
2177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the (only) argument into v0.
2180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(v0, MemOperand(sp, 0 * kPointerSize));
2181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check if the argument is a smi.
2183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label not_smi;
2184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
2185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(v0, &not_smi);
2186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Do bitwise not or do nothing depending on the sign of the
2188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // argument.
2189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sra(t0, v0, kBitsPerInt - 1);
2190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Xor(a1, v0, t0);
2191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Add 1 or do nothing depending on the sign of the argument.
2193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Subu(v0, a1, t0);
2194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If the result is still negative, go to the slow case.
2196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This only happens for the most negative smi.
2197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label slow;
2198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&slow, lt, v0, Operand(zero_reg));
2199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Smi case done.
2201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(argc + 1);
2202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
2203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check if the argument is a heap number and load its exponent and
2205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // sign.
2206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&not_smi);
2207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
2208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset));
2209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check the sign of the argument. If the argument is positive,
2211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // just return it.
2212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label negative_sign;
2213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(t0, a1, Operand(HeapNumber::kSignMask));
2214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&negative_sign, ne, t0, Operand(zero_reg));
2215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(argc + 1);
2216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
2217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If the argument is negative, clear the sign, and return a new
2219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // number.
2220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&negative_sign);
2221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Xor(a1, a1, Operand(HeapNumber::kSignMask));
2222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset));
2223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex);
2224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AllocateHeapNumber(v0, t0, t1, t2, &slow);
2225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset));
2226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset));
2227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(argc + 1);
2228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
2229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Tail call the full function. We do not have to patch the receiver
2231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // because the function makes no use of it.
2232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&slow);
22333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(
22343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
2235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2: function name.
22383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
22423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
22433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22453ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall(
224644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    const CallOptimization& optimization,
22473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = isolate()->counters();
2254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(optimization.is_simple_api_call());
2256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Bail out if object is a global object as we don't want to
2257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // repatch it to global receiver.
22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (object->IsGlobalObject()) return Handle<Code>::null();
22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!cell.is_null()) return Handle<Code>::null();
22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject()) return Handle<Code>::null();
2261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int depth = optimization.GetPrototypeDepthOfExpectedType(
22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<JSObject>::cast(object), holder);
22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (depth == kInvalidProtoDepth) return Handle<Code>::null();
2264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss, miss_before_stack_reserved;
2266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateNameCheck(name, &miss_before_stack_reserved);
2268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the receiver from the stack.
2270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int argc = arguments().immediate();
2271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a1, MemOperand(sp, argc * kPointerSize));
2272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the receiver isn't a smi.
2274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(a1, &miss_before_stack_reserved);
2275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->call_const(), 1, a0, a3);
2277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a3);
2278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ReserveSpaceForFastApiCall(masm(), a0);
2280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the maps haven't changed and find a Holder as a side effect.
22823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0, name,
2283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  depth, &miss);
2284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
22853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateFastApiDirectCall(masm(), optimization, argc);
2286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  FreeSpaceForFastApiCall(masm());
2289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_before_stack_reserved);
22913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(function);
22953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
22963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
22983ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> function,
23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
230244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   CheckType check) {
2303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
2305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (HasCustomCallGenerator(function)) {
23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder,
23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Handle<JSGlobalPropertyCell>::null(),
23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          function, name);
23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
23123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
2313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateNameCheck(name, &miss);
2318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the receiver from the stack.
2320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int argc = arguments().immediate();
2321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a1, MemOperand(sp, argc * kPointerSize));
2322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the receiver isn't a smi.
2324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (check != NUMBER_CHECK) {
23253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(a1, &miss);
2326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Make sure that it's okay not to patch the on stack receiver
2329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // unless we're doing a receiver map check.
2330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  switch (check) {
2332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case RECEIVER_MAP_CHECK:
2333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ IncrementCounter(masm()->isolate()->counters()->call_const(),
2334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          1, a0, a3);
2335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Check that the maps haven't changed.
23373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0,
23383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      name, &miss);
2339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Patch the receiver on the stack with the global proxy if
2341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // necessary.
2342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (object->IsGlobalObject()) {
2343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ lw(a3, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset));
2344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sw(a3, MemOperand(sp, argc * kPointerSize));
2345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
2346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
2347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case STRING_CHECK:
23493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Check that the object is a two-byte string or a symbol.
2351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ GetObjectType(a1, a3, a3);
2352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE));
2353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Check that the maps starting from the prototype haven't changed.
2354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
2355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            masm(), Context::STRING_FUNCTION_INDEX, a0, &miss);
23563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
23573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
23583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            a0, holder, a3, a1, t0, name, &miss);
23593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
236085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
236185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // requires boxing.
236285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        __ jmp(&miss);
23633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
23643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
23653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case NUMBER_CHECK:
23673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label fast;
2369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Check that the object is a smi or a heap number.
23703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ JumpIfSmi(a1, &fast);
2371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ GetObjectType(a1, a0, a0);
2372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&miss, ne, a0, Operand(HEAP_NUMBER_TYPE));
2373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ bind(&fast);
2374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Check that the maps starting from the prototype haven't changed.
2375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
2376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            masm(), Context::NUMBER_FUNCTION_INDEX, a0, &miss);
23773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
23783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
23793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            a0, holder, a3, a1, t0, name, &miss);
23803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
238185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
238285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // requires boxing.
238385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        __ jmp(&miss);
23843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
23853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case BOOLEAN_CHECK:
23883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Label fast;
2390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Check that the object is a boolean.
2391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ LoadRoot(t0, Heap::kTrueValueRootIndex);
2392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&fast, eq, a1, Operand(t0));
2393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ LoadRoot(t0, Heap::kFalseValueRootIndex);
2394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&miss, ne, a1, Operand(t0));
2395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ bind(&fast);
2396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Check that the maps starting from the prototype haven't changed.
2397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
2398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            masm(), Context::BOOLEAN_FUNCTION_INDEX, a0, &miss);
23993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
24003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
24013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            a0, holder, a3, a1, t0, name, &miss);
24023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
24033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
24043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // requires boxing.
24053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&miss);
2406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
2407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
2408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
2409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
24103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
24113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ? CALL_AS_FUNCTION
24123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : CALL_AS_METHOD;
24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(
24143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind);
2415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle call cache miss.
2417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
24193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(function);
24233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
24243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
24253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
24263ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
24273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
2429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
2431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateNameCheck(name, &miss);
2437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the number of arguments.
2439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int argc = arguments().immediate();
24403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
2441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LookupPostInterceptor(holder, name, &lookup);
2442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the receiver from the stack.
2444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a1, MemOperand(sp, argc * kPointerSize));
2445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
24463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallInterceptorCompiler compiler(this, arguments(), a2, extra_state_);
24473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  compiler.Compile(masm(), object, holder, name, &lookup, a1, a3, t0, a0,
24483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   &miss);
2449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Move returned value, the function to call, to a1.
2451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(a1, v0);
2452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Restore receiver.
2453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a0, MemOperand(sp, argc * kPointerSize));
2454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
24553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
2456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle call cache miss.
2458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
24593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(INTERCEPTOR, name);
24633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
24643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
24653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
24663ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal(
24673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
24693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
24713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
2474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (HasCustomCallGenerator(function)) {
24783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
24793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
24803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
2481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateNameCheck(name, &miss);
2485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the number of arguments.
2487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int argc = arguments().immediate();
2488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateGlobalReceiverCheck(object, holder, name, &miss);
2489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadFunctionFromCell(cell, function, &miss);
2490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Patch the receiver on the stack with the global proxy if
2492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // necessary.
2493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (object->IsGlobalObject()) {
2494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset));
2495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(a3, MemOperand(sp, argc * kPointerSize));
2496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
24983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the context (function already in r1).
2499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
2500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Jump to the cached code (tail call).
2502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm()->isolate()->counters();
2503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->call_global_inline(), 1, a3, t0);
2504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ParameterCount expected(function->shared()->formal_parameter_count());
25053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
25083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We call indirectly through the code field in the function to
25093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // allow recompilation to take effect without changing any of the
25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // call sites.
25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
25123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION,
25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                NullCallWrapper(), call_kind);
2514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle call cache miss.
2516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3);
25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(NORMAL, name);
25223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
25233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
25243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
252644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  int index,
25273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<Map> transition,
25283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<String> name) {
2529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : value
2531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
2532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
2533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Name register might be clobbered.
25383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, a1, a2, a3, &miss);
2539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ li(a2, Operand(Handle<String>(name)));  // Restore name.
2541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm()->isolate()->builtins()->Builtins::StoreIC_Miss();
2542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
2543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
25453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
25463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
25473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
25483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
25493ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback(
25503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
25513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback,
25523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : value
2555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
2556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
2557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the map of the object hasn't changed.
25623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(a1, a3, Handle<Map>(object->map()), &miss,
25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Perform global security token check if needed.
2566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (object->IsJSGlobalProxy()) {
2567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ CheckAccessGlobalProxy(a1, a3, &miss);
2568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Stub never generated for non-global objects that require access
2571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // checks.
2572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(a1);  // Receiver.
25753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a3, Operand(callback));  // Callback info.
2576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Push(a3, a2, a0);
2577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Do tail-call to the runtime system.
2579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference store_callback_property =
2580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ExternalReference(IC_Utility(IC::kStoreCallbackProperty),
2581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          masm()->isolate());
2582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ TailCallExternalReference(store_callback_property, 4, 1);
2583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle store cache miss.
2585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
2587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
2588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(CALLBACKS, name);
259144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
259244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
259344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
25943ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor(
25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
25963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : value
2599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
2600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
2601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the map of the object hasn't changed.
26063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(a1, a3, Handle<Map>(receiver->map()), &miss,
26073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Perform global security token check if needed.
2610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (receiver->IsJSGlobalProxy()) {
2611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ CheckAccessGlobalProxy(a1, a3, &miss);
2612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Stub is never generated for non-global objects that require access
2615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // checks.
2616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Push(a1, a2, a0);  // Receiver, name, value.
2619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ li(a0, Operand(Smi::FromInt(strict_mode_)));
2621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(a0);  // Strict mode.
2622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Do tail-call to the runtime system.
2624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference store_ic_property =
2625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty),
2626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          masm()->isolate());
2627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ TailCallExternalReference(store_ic_property, 4, 1);
2628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle store cache miss.
2630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm()->isolate()->builtins()->Builtins::StoreIC_Miss();
2632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
2633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(INTERCEPTOR, name);
263644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
263744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
263844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
26393ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal(
26403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> object,
26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : value
2645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
2646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
2647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the map of the global has not changed.
2652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset));
2653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&miss, ne, a3, Operand(Handle<Map>(object->map())));
2654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the value in the cell is not the hole. If it is, this
2656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // cell could have been deleted and reintroducing the global needs
2657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // to update the property details in the property dictionary of the
2658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // global object. We bail out to the runtime system to do that.
26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(t0, Operand(cell));
2660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(t1, Heap::kTheHoleValueRootIndex);
2661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(t2, FieldMemOperand(t0, JSGlobalPropertyCell::kValueOffset));
2662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&miss, eq, t1, Operand(t2));
2663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Store the value in the cell.
2665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a0, FieldMemOperand(t0, JSGlobalPropertyCell::kValueOffset));
2666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(v0, a0);  // Stored value must be returned in v0.
26673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Cells are always rescanned, so no write barrier here.
26683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm()->isolate()->counters();
2670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->named_store_global_inline(), 1, a1, a3);
2671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
2672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle store cache miss.
2674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->named_store_global_inline_miss(), 1, a1, a3);
2676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
2677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
2678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(NORMAL, name);
268144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
268244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
268344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
26843ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
26853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> object,
26863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> last) {
2687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : receiver
2689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the receiver is not a smi.
2694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(a0, &miss);
2695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check the maps of the full prototype chain.
2697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CheckPrototypes(object, a0, last, a3, a1, t0, name, &miss);
2698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If the last object in the prototype chain is a global object,
2700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // check that the global property cell is empty.
2701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (last->IsGlobalObject()) {
27023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateCheckPropertyCell(
27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm(), Handle<GlobalObject>::cast(last), name, a1, &miss);
2704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return undefined if maps of the full prototype chain is still the same.
2707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
2708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
2709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::LOAD_IC);
2712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
27143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NONEXISTENT, factory()->empty_string());
271544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
271644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
271744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
27183ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
272044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                int index,
27213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
2722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : receiver
2724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
2725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(v0, a0);
2730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadField(object, holder, v0, a3, a1, t0, index, name, &miss);
2732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::LOAD_IC);
2734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(FIELD, name);
27373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
27383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback(
27413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
27423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
27443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
2745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : receiver
2747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
2748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
27513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(object, holder, a0, a2, a3, a1, t0, callback, name,
27523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       &miss);
2753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::LOAD_IC);
2755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(CALLBACKS, name);
27583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
27593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
27633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> value,
27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name) {
2765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : receiver
2767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
2768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadConstant(object, holder, a0, a3, a1, t0, value, name, &miss);
2773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::LOAD_IC);
2775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(CONSTANT_FUNCTION, name);
27783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
27793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
27813ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object,
27823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
27833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
2784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : receiver
2786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
2787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- [sp]  : receiver
2789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
27923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
2793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LookupPostInterceptor(holder, name, &lookup);
27943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(object, holder, &lookup, a0, a2, a3, a1, t0, name,
2795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          &miss);
2796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::LOAD_IC);
2798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(INTERCEPTOR, name);
28013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
28023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal(
28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
28073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_dont_delete) {
2810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : receiver
2812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : name
2813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the map of the global has not changed.
28183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(a0, &miss);
2819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CheckPrototypes(object, a0, holder, a3, t0, a1, name, &miss);
2820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the value from the cell.
28223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a3, Operand(cell));
2823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(t0, FieldMemOperand(a3, JSGlobalPropertyCell::kValueOffset));
2824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for deleted property if property can actually be deleted.
2826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!is_dont_delete) {
2827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&miss, eq, t0, Operand(at));
2829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
2830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(v0, t0);
2832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm()->isolate()->counters();
2833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3);
2834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
2835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->named_load_global_stub_miss(), 1, a1, a3);
2838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::LOAD_IC);
2839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(NORMAL, name);
28423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
28433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28453ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
28463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> receiver,
28473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> holder,
284844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                     int index) {
2849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : key
2852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
2853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check the key is the cached one.
28573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&miss, ne, a0, Operand(name));
2858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadField(receiver, holder, a1, a2, a3, t0, index, name, &miss);
2860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(FIELD, name);
28643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
28653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback(
28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
28703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
28713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
2872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : key
2875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
2876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check the key is the cached one.
28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&miss, ne, a0, Operand(name));
2881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
28823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(receiver, holder, a1, a0, a2, a3, t0, callback, name,
28833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       &miss);
2884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(CALLBACKS, name);
28883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
28893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
28913ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant(
28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
28943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
28953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> value) {
2896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : key
2899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
2900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check the key is the cached one.
29043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&miss, ne, a0, Operand(name));
2905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadConstant(receiver, holder, a1, a2, a3, t0, value, name, &miss);
2907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(CONSTANT_FUNCTION, name);
291244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
291344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
291444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
29153ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
29163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
29173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
29183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : key
2922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
2923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check the key is the cached one.
29273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&miss, ne, a0, Operand(name));
2928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
2930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LookupPostInterceptor(holder, name, &lookup);
29313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(receiver, holder, &lookup, a1, a0, a2, a3, t0, name,
2932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          &miss);
2933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(INTERCEPTOR, name);
293744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
293844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
293944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
29403ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
29413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : key
2945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
2946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check the key is the cached one.
29503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&miss, ne, a0, Operand(name));
2951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadArrayLength(masm(), a1, a2, &miss);
2953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(CALLBACKS, name);
295744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
295844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
295944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
29603ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
29613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : key
2965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
2966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm()->isolate()->counters();
2970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->keyed_load_string_length(), 1, a2, a3);
2971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check the key is the cached one.
29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&miss, ne, a0, Operand(name));
2974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadStringLength(masm(), a1, a2, a3, &miss, true);
2976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
2977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ DecrementCounter(counters->keyed_load_string_length(), 1, a2, a3);
2978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(CALLBACKS, name);
298244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
298344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
298444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
29853ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
29863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
2989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : key
2990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
2991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm()->isolate()->counters();
2995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3);
2996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check the name hasn't changed.
29983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&miss, ne, a0, Operand(name));
2999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadFunctionPrototype(masm(), a1, a2, a3, &miss);
3001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
3002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ DecrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3);
3003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode(CALLBACKS, name);
300644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
300744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
300844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement(
30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
3011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
3013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : key
3014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
3015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3016589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
30173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode();
30183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK);
3020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
3023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
30253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
3026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic(
30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_ics) {
3032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
3034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : key
3035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
3036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
3038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(a1, &miss);
3039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int receiver_count = receiver_maps->length();
3041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset));
3042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int current = 0; current < receiver_count; ++current) {
30433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Jump(handler_ics->at(current), RelocInfo::CODE_TARGET,
30443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        eq, a2, Operand(receiver_maps->at(current)));
3045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
3048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss();
3049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
3050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
30523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
305344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
305444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
305544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
30563ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
305744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                       int index,
30583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<Map> transition,
30593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<String> name) {
3060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : value
3062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : key
3063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : receiver
3064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
3065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
3068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm()->isolate()->counters();
3070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->keyed_store_field(), 1, a3, t0);
3071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the name has not changed.
30733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&miss, ne, a1, Operand(name));
3074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a3 is used as scratch register. a1 and a2 keep their values if a jump to
3076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the miss label is generated.
30773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, a2, a1, a3, &miss);
3078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
3079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ DecrementCounter(counters->keyed_store_field(), 1, a3, t0);
3081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
3082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
3083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
30853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
308644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
308744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
308844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
30893ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement(
30903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
3091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : value
3093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : key
3094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : receiver
3095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
3096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a3    : scratch
3097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3098589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
3099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
31003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub =
31013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode();
31023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(a2, a3, receiver_map, stub, DO_SMI_CHECK);
3104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
3107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
31093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
3110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
31133ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
31143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
31153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_stubs,
31163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* transitioned_maps) {
3117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : value
3119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : key
3120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : receiver
3121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a3    : scratch
3123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
3125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(a2, &miss);
3126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int receiver_count = receiver_maps->length();
3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a3, FieldMemOperand(a2, HeapObject::kMapOffset));
31293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < receiver_count; ++i) {
31303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (transitioned_maps->at(i).is_null()) {
31313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq,
31323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          a3, Operand(receiver_maps->at(i)));
31333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
31343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label next_map;
31353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&next_map, ne, a3, Operand(receiver_maps->at(i)));
31363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ li(a3, Operand(transitioned_maps->at(i)));
31373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET);
31383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&next_map);
31393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
3143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
3144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
3145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
31473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
31483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
31493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
31503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub(
31523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function) {
3153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0    : argc
3154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1    : constructor
3155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ra    : return address
3156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // [sp]  : last argument
3157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label generic_stub_call;
3158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Use t7 for holding undefined which is used in several places below.
3160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
3161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef ENABLE_DEBUGGER_SUPPORT
3163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check to see whether there are any break points in the function code. If
3164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // there are jump to the generic constructor stub which calls the actual
3165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // code for the function thereby hitting the break points.
3166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(t5, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
3167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a2, FieldMemOperand(t5, SharedFunctionInfo::kDebugInfoOffset));
3168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&generic_stub_call, ne, a2, Operand(t7));
3169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
3170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the initial map and verify that it is in fact a map.
3172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: constructor function
3173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t7: undefined
3174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
31753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(a2, &generic_stub_call);
3176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ GetObjectType(a2, a3, t0);
3177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&generic_stub_call, ne, t0, Operand(MAP_TYPE));
3178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG
3180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Cannot construct functions this way.
3181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: argc
3182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: constructor function
3183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2: initial map
3184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t7: undefined
3185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
3186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Check(ne, "Function constructed by construct stub.",
3187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      a3, Operand(JS_FUNCTION_TYPE));
3188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
3189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Now allocate the JSObject in new space.
3191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: argc
3192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: constructor function
3193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2: initial map
3194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t7: undefined
3195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
31963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AllocateInNewSpace(a3, t4, t5, t6, &generic_stub_call, SIZE_IN_WORDS);
3197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Allocated the JSObject, now initialize the fields. Map is set to initial
3199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // map and properties and elements are set to empty fixed array.
3200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: argc
3201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: constructor function
3202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2: initial map
3203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a3: object size (in words)
3204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t4: JSObject (not tagged)
3205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t7: undefined
3206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(t6, Heap::kEmptyFixedArrayRootIndex);
3207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(t5, t4);
3208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a2, MemOperand(t5, JSObject::kMapOffset));
3209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(t6, MemOperand(t5, JSObject::kPropertiesOffset));
3210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(t6, MemOperand(t5, JSObject::kElementsOffset));
3211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(t5, t5, Operand(3 * kPointerSize));
3212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
3213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
3214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
3215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Calculate the location of the first argument. The stack contains only the
3218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // argc arguments.
3219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(a1, a0, kPointerSizeLog2);
3220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(a1, a1, sp);
3221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Fill all the in-object properties with undefined.
3223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: argc
3224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: first argument
3225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a3: object size (in words)
3226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t4: JSObject (not tagged)
3227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t5: First in-object property of JSObject (not tagged)
3228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t7: undefined
3229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Fill the initialized properties with a constant value or a passed argument
3230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // depending on the this.x = ...; assignment in the function.
32313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<SharedFunctionInfo> shared(function->shared());
3232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
3233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (shared->IsThisPropertyAssignmentArgument(i)) {
3234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label not_passed, next;
3235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Check if the argument assigned to the property is actually passed.
3236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      int arg_number = shared->GetThisPropertyAssignmentArgument(i);
3237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Branch(&not_passed, less_equal, a0, Operand(arg_number));
3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Argument passed - find it on the stack.
3239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ lw(a2, MemOperand(a1, (arg_number + 1) * -kPointerSize));
3240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(a2, MemOperand(t5));
3241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Addu(t5, t5, kPointerSize);
3242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ jmp(&next);
3243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ bind(&not_passed);
3244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Set the property to undefined.
3245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(t7, MemOperand(t5));
3246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Addu(t5, t5, Operand(kPointerSize));
3247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ bind(&next);
3248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Set the property to the constant value.
3250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
3251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ li(a2, Operand(constant));
3252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(a2, MemOperand(t5));
3253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Addu(t5, t5, kPointerSize);
3254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Fill the unused in-object property fields with undefined.
3258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(function->has_initial_map());
3259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = shared->this_property_assignments_count();
3260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       i < function->initial_map()->inobject_properties();
3261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       i++) {
3262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(t7, MemOperand(t5));
3263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Addu(t5, t5, kPointerSize);
3264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: argc
3267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t4: JSObject (not tagged)
3268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Move argc to a1 and the JSObject to return to v0 and tag it.
3269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(a1, a0);
3270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(v0, t4);
3271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Or(v0, v0, Operand(kHeapObjectTag));
3272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // v0: JSObject
3274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: argc
3275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Remove caller arguments and receiver from the stack and return.
3276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(t0, a1, kPointerSizeLog2);
3277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, t0);
3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, Operand(kPointerSize));
3279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm()->isolate()->counters();
3280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->constructed_objects(), 1, a1, a2);
3281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->constructed_objects_stub(), 1, a1, a2);
3282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
3283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Jump to the generic stub in case the specialized code cannot handle the
3285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // construction.
3286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&generic_stub_call);
3287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> generic_construct_stub =
3288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm()->isolate()->builtins()->JSConstructStubGeneric();
3289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
3290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
3292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return GetCode();
32933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
32943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
32953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
32963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __
32973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm)
3298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
33013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
33023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ---------- S t a t e --------------
33033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ra     : return address
33043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- a0     : key
33053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- a1     : receiver
33063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
33073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, miss_force_generic;
33081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register key = a0;
33103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register receiver = a1;
33111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(key, &miss_force_generic);
33133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ lw(t0, FieldMemOperand(receiver, JSObject::kElementsOffset));
33143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ sra(a2, a0, kSmiTagSize);
33153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadFromNumberDictionary(&slow, t0, a0, v0, a2, a3, t1);
33163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
3317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Slow case, key and receiver still in a0 and a1.
33193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
33203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ IncrementCounter(
33213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->counters()->keyed_load_external_array_slow(),
33223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      1, a2, a3);
33233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Entry registers are intact.
33243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ---------- S t a t e --------------
33253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ra     : return address
33263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- a0     : key
33273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- a1     : receiver
33283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
33293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
33303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
33313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(slow_ic, RelocInfo::CODE_TARGET);
3332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Miss case, call the runtime.
33343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
3335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ---------- S t a t e --------------
33373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ra     : return address
33383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- a0     : key
33393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- a1     : receiver
33403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
3341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_ic =
33433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch     masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
33443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
33453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
3346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochstatic bool IsElementTypeSigned(ElementsKind elements_kind) {
33493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
3351589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
3352589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
3353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return true;
3354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3356589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3357589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3358589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
3359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return false;
3360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
3362589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
33633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case FAST_SMI_ONLY_ELEMENTS:
3364589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_ELEMENTS:
3365589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_DOUBLE_ELEMENTS:
3366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case DICTIONARY_ELEMENTS:
3367589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case NON_STRICT_ARGUMENTS_ELEMENTS:
3368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      UNREACHABLE();
3369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return false;
3370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
33713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return false;
3372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray(
3376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3377589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
3378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ---------- S t a t e --------------
3379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
3380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0     : key
3381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1     : receiver
3382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic, slow, failed_allocation;
3384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register key = a0;
3386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register receiver = a1;
3387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
3390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
3392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(key, &miss_force_generic);
3393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset));
3395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a3: elements array
3396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the index is in range.
3398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset));
3399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sra(t2, key, kSmiTagSize);
3400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Unsigned comparison catches both negative and too-large values.
340169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ Branch(&miss_force_generic, Ugreater_equal, key, Operand(t1));
3402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset));
3404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a3: base pointer of external storage
3405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We are not untagging smi key and instead work with it
3407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // as if it was premultiplied by 2.
3408589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
3409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register value = a2;
34113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3412589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
3413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ srl(t2, key, 1);
3414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ addu(t3, a3, t2);
3415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ lb(value, MemOperand(t3, 0));
3416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3417589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
3418589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ srl(t2, key, 1);
3420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ addu(t3, a3, t2);
3421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ lbu(value, MemOperand(t3, 0));
3422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3423589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
3424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ addu(t3, a3, key);
3425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ lh(value, MemOperand(t3, 0));
3426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ addu(t3, a3, key);
3429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ lhu(value, MemOperand(t3, 0));
3430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3431589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
3432589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sll(t2, key, 1);
3434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ addu(t3, a3, t2);
3435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ lw(value, MemOperand(t3, 0));
3436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3437589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
3438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sll(t3, t2, 2);
3439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ addu(t3, a3, t3);
3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (CpuFeatures::IsSupported(FPU)) {
3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        CpuFeatures::Scope scope(FPU);
3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ lwc1(f0, MemOperand(t3, 0));
3443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ lw(value, MemOperand(t3, 0));
3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
3446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3447589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sll(t2, key, 2);
3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ addu(t3, a3, t2);
3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (CpuFeatures::IsSupported(FPU)) {
3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        CpuFeatures::Scope scope(FPU);
3452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ ldc1(f0, MemOperand(t3, 0));
3453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
3454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // t3: pointer to the beginning of the double we want to load.
3455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ lw(a2, MemOperand(t3, 0));
3456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ lw(a3, MemOperand(t3, Register::kSizeInBytes));
3457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
3458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3459589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_ELEMENTS:
34603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case FAST_SMI_ONLY_ELEMENTS:
3461589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_DOUBLE_ELEMENTS:
3462589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case DICTIONARY_ELEMENTS:
3463589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case NON_STRICT_ARGUMENTS_ELEMENTS:
3464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      UNREACHABLE();
3465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // For integer array types:
3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2: value
3470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // For float array type:
3471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // f0: value (if FPU is supported)
3472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2: value (if FPU is not supported)
3473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // For double array type:
3474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // f0: value (if FPU is supported)
3475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2/a3: value (if FPU is not supported)
3476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3477589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_INT_ELEMENTS) {
3478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // For the Int and UnsignedInt array types, we need to see whether
3479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // the value can be represented in a Smi. If not, we need to convert
3480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // it to a HeapNumber.
3481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label box_int;
3482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Subu(t3, value, Operand(0xC0000000));  // Non-smi value gives neg result.
3483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&box_int, lt, t3, Operand(zero_reg));
3484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Tag integer as smi and return it.
3485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(v0, value, kSmiTagSize);
3486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Ret();
3487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&box_int);
3489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Allocate a HeapNumber for the result and perform int-to-double
3490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // conversion.
3491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The arm version uses a temporary here to save r0, but we don't need to
3492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // (a0 is not modified).
3493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(t1, Heap::kHeapNumberMapRootIndex);
3494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ AllocateHeapNumber(v0, a3, t0, t1, &slow);
3495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (CpuFeatures::IsSupported(FPU)) {
3497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CpuFeatures::Scope scope(FPU);
3498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ mtc1(value, f0);
3499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ cvt_d_w(f0, f0);
3500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sdc1(f0, MemOperand(v0, HeapNumber::kValueOffset - kHeapObjectTag));
3501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Register dst1 = t2;
3504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Register dst2 = t3;
3505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FloatingPointHelper::Destination dest =
3506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          FloatingPointHelper::kCoreRegisters;
3507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FloatingPointHelper::ConvertIntToDouble(masm,
3508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              value,
3509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              dest,
3510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              f0,
3511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              dst1,
3512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              dst2,
3513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              t1,
3514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              f2);
3515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(dst1, FieldMemOperand(v0, HeapNumber::kMantissaOffset));
3516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(dst2, FieldMemOperand(v0, HeapNumber::kExponentOffset));
3517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3519589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
3520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The test is different for unsigned int values. Since we need
3521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // the value to be in the range of a positive smi, we can't
3522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // handle either of the top two bits being set in the value.
3523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (CpuFeatures::IsSupported(FPU)) {
3524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CpuFeatures::Scope scope(FPU);
3525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label pl_box_int;
3526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ And(t2, value, Operand(0xC0000000));
3527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Branch(&pl_box_int, ne, t2, Operand(zero_reg));
3528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // It can fit in an Smi.
3530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Tag integer as smi and return it.
3531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sll(v0, value, kSmiTagSize);
3532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ bind(&pl_box_int);
3535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Allocate a HeapNumber for the result and perform int-to-double
3536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // conversion. Don't use a0 and a1 as AllocateHeapNumber clobbers all
3537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // registers - also when jumping due to exhausted young space.
3538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex);
3539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ AllocateHeapNumber(v0, t2, t3, t6, &slow);
3540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // This is replaced by a macro:
3542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // __ mtc1(value, f0);     // LS 32-bits.
3543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // __ mtc1(zero_reg, f1);  // MS 32-bits are all zero.
3544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // __ cvt_d_l(f0, f0); // Use 64 bit conv to get correct unsigned 32-bit.
3545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
354669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ Cvt_d_uw(f0, value, f22);
3547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sdc1(f0, MemOperand(v0, HeapNumber::kValueOffset - kHeapObjectTag));
3549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Check whether unsigned integer fits into smi.
3553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label box_int_0, box_int_1, done;
3554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ And(t2, value, Operand(0x80000000));
3555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Branch(&box_int_0, ne, t2, Operand(zero_reg));
3556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ And(t2, value, Operand(0x40000000));
3557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Branch(&box_int_1, ne, t2, Operand(zero_reg));
3558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Tag integer as smi and return it.
3560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sll(v0, value, kSmiTagSize);
3561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Register hiword = value;  // a2.
3564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Register loword = a3;
3565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ bind(&box_int_0);
3567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Integer does not have leading zeros.
3568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      GenerateUInt2Double(masm, hiword, loword, t0, 0);
3569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Branch(&done);
3570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ bind(&box_int_1);
3572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Integer has one leading zero.
3573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      GenerateUInt2Double(masm, hiword, loword, t0, 1);
3574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ bind(&done);
3577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Integer was converted to double in registers hiword:loword.
3578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Wrap it into a HeapNumber. Don't use a0 and a1 as AllocateHeapNumber
3579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // clobbers all registers - also when jumping due to exhausted young
3580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // space.
3581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex);
3582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ AllocateHeapNumber(t2, t3, t5, t6, &slow);
3583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(hiword, FieldMemOperand(t2, HeapNumber::kExponentOffset));
3585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(loword, FieldMemOperand(t2, HeapNumber::kMantissaOffset));
3586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ mov(v0, t2);
3588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3590589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
3591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // For the floating-point array type, we need to always allocate a
3592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // HeapNumber.
3593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (CpuFeatures::IsSupported(FPU)) {
3594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CpuFeatures::Scope scope(FPU);
3595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Allocate a HeapNumber for the result. Don't use a0 and a1 as
3596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // AllocateHeapNumber clobbers all registers - also when jumping due to
3597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // exhausted young space.
3598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex);
3599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ AllocateHeapNumber(v0, t3, t5, t6, &slow);
3600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // The float (single) value is already in fpu reg f0 (if we use float).
3601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ cvt_d_s(f0, f0);
3602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sdc1(f0, MemOperand(v0, HeapNumber::kValueOffset - kHeapObjectTag));
3603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Allocate a HeapNumber for the result. Don't use a0 and a1 as
3606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // AllocateHeapNumber clobbers all registers - also when jumping due to
3607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // exhausted young space.
3608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex);
3609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ AllocateHeapNumber(v0, t3, t5, t6, &slow);
3610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // FPU is not available, do manual single to double conversion.
3611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // a2: floating point value (binary32).
3613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // v0: heap number for result
3614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Extract mantissa to t4.
3616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ And(t4, value, Operand(kBinary32MantissaMask));
3617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Extract exponent to t5.
3619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ srl(t5, value, kBinary32MantissaBits);
3620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ And(t5, t5, Operand(kBinary32ExponentMask >> kBinary32MantissaBits));
3621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label exponent_rebiased;
3623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Branch(&exponent_rebiased, eq, t5, Operand(zero_reg));
3624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ li(t0, 0x7ff);
3626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Xor(t1, t5, Operand(0xFF));
36273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Movz(t5, t0, t1);  // Set t5 to 0x7ff only if t5 is equal to 0xff.
3628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Branch(&exponent_rebiased, eq, t0, Operand(0xff));
3629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Rebias exponent.
3631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Addu(t5,
3632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              t5,
3633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              Operand(-kBinary32ExponentBias + HeapNumber::kExponentBias));
3634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ bind(&exponent_rebiased);
3636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ And(a2, value, Operand(kBinary32SignMask));
3637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      value = no_reg;
3638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sll(t0, t5, HeapNumber::kMantissaBitsInTopWord);
3639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ or_(a2, a2, t0);
3640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Shift mantissa.
3642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      static const int kMantissaShiftForHiWord =
3643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
3644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      static const int kMantissaShiftForLoWord =
3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          kBitsPerInt - kMantissaShiftForHiWord;
3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ srl(t0, t4, kMantissaShiftForHiWord);
3649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ or_(a2, a2, t0);
3650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sll(a0, t4, kMantissaShiftForLoWord);
3651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(a2, FieldMemOperand(v0, HeapNumber::kExponentOffset));
3653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(a0, FieldMemOperand(v0, HeapNumber::kMantissaOffset));
3654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3657589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (CpuFeatures::IsSupported(FPU)) {
3659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CpuFeatures::Scope scope(FPU);
3660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Allocate a HeapNumber for the result. Don't use a0 and a1 as
3661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // AllocateHeapNumber clobbers all registers - also when jumping due to
3662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // exhausted young space.
3663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex);
3664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ AllocateHeapNumber(v0, t3, t5, t6, &slow);
3665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // The double value is already in f0
3666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset));
3667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Allocate a HeapNumber for the result. Don't use a0 and a1 as
3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // AllocateHeapNumber clobbers all registers - also when jumping due to
3671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // exhausted young space.
3672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex);
3673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ AllocateHeapNumber(v0, t3, t5, t6, &slow);
3674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(a2, FieldMemOperand(v0, HeapNumber::kMantissaOffset));
3676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(a3, FieldMemOperand(v0, HeapNumber::kExponentOffset));
3677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Tag integer as smi and return it.
3682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(v0, value, kSmiTagSize);
3683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Ret();
3684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Slow case, key and receiver still in a0 and a1.
3687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&slow);
3688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(
3689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->counters()->keyed_load_external_array_slow(),
3690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      1, a2, a3);
3691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ---------- S t a t e --------------
3693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
3694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0     : key
3695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1     : receiver
3696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Push(a1, a0);
3699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
3701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
37033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub =
37043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
37053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(stub, RelocInfo::CODE_TARGET);
3706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray(
3710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3711589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
3712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ---------- S t a t e --------------
3713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0     : value
3714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1     : key
3715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2     : receiver
3716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
3717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label slow, check_heap_number, miss_force_generic;
3720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Register usage.
3722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register value = a0;
3723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register key = a1;
3724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register receiver = a2;
3725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a3 mostly holds the elements array or the destination external array.
3726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
3729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
373069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Check that the key is a smi.
3731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(key, &miss_force_generic);
3732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
373369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset));
373469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
3735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the index is in range.
3736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset));
3737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Unsigned comparison catches both negative and too-large values.
373869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ Branch(&miss_force_generic, Ugreater_equal, key, Operand(t1));
3739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle both smis and HeapNumbers in the fast path. Go to the
3741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // runtime for all other kinds of values.
3742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a3: external array.
3743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3744589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
3745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Double to pixel conversion is only implemented in the runtime for now.
3746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfNotSmi(value, &slow);
3747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfNotSmi(value, &check_heap_number);
3749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ SmiUntag(t1, value);
3751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset));
3752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a3: base pointer of external storage.
3754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t1: value (integer).
3755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
37563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3757589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS: {
3758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Clamp the value to [0..255].
3759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // v0 is used as a scratch register here.
3760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label done;
3761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ li(v0, Operand(255));
3762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Normal branch: nop in delay slot.
3763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Branch(&done, gt, t1, Operand(v0));
3764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Use delay slot in this branch.
3765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Branch(USE_DELAY_SLOT, &done, lt, t1, Operand(zero_reg));
3766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ mov(v0, zero_reg);  // In delay slot.
3767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ mov(v0, t1);  // Value is in range 0..255.
3768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ bind(&done);
3769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ mov(t1, v0);
37703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ srl(t8, key, 1);
37723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ addu(t8, a3, t8);
3773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sb(t1, MemOperand(t8, 0));
3774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
3775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3776589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
3777589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
37783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ srl(t8, key, 1);
37793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ addu(t8, a3, t8);
3780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sb(t1, MemOperand(t8, 0));
3781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3782589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
3783589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ addu(t8, a3, key);
3785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sh(t1, MemOperand(t8, 0));
3786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3787589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
3788589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
37893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sll(t8, key, 1);
3790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ addu(t8, a3, t8);
3791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sw(t1, MemOperand(t8, 0));
3792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3793589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
3794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Perform int-to-float conversion and store to memory.
37953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ SmiUntag(t0, key);
3796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      StoreIntAsFloat(masm, a3, t0, t1, t2, t3, t4);
3797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3798589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
37993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sll(t8, key, 2);
3800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ addu(a3, a3, t8);
3801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // a3: effective address of the double element
3802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FloatingPointHelper::Destination destination;
3803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (CpuFeatures::IsSupported(FPU)) {
3804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        destination = FloatingPointHelper::kFPURegisters;
3805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
3806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        destination = FloatingPointHelper::kCoreRegisters;
3807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
3808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FloatingPointHelper::ConvertIntToDouble(
3809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          masm, t1, destination,
3810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          f0, t2, t3,  // These are: double_dst, dst1, dst2.
3811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          t0, f2);  // These are: scratch2, single_scratch.
3812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (destination == FloatingPointHelper::kFPURegisters) {
3813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        CpuFeatures::Scope scope(FPU);
3814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sdc1(f0, MemOperand(a3, 0));
3815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
3816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sw(t2, MemOperand(a3, 0));
3817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sw(t3, MemOperand(a3, Register::kSizeInBytes));
3818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
3819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3820589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_ELEMENTS:
38213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case FAST_SMI_ONLY_ELEMENTS:
3822589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_DOUBLE_ELEMENTS:
3823589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case DICTIONARY_ELEMENTS:
3824589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case NON_STRICT_ARGUMENTS_ELEMENTS:
3825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      UNREACHABLE();
3826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Entry registers are intact, a0 holds the value which is the return value.
38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(v0, a0);
3831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
3832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3833589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
3834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a3: external array.
3835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&check_heap_number);
3836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ GetObjectType(value, t1, t2);
3837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&slow, ne, t2, Operand(HEAP_NUMBER_TYPE));
3838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset));
3840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a3: base pointer of external storage.
3842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The WebGL specification leaves the behavior of storing NaN and
3844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // +/-Infinity into integer arrays basically undefined. For more
3845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // reproducible behavior, convert these to zero.
3846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (CpuFeatures::IsSupported(FPU)) {
3848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CpuFeatures::Scope scope(FPU);
3849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ ldc1(f0, FieldMemOperand(a0, HeapNumber::kValueOffset));
3851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3852589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
3853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ cvt_s_d(f0, f0);
38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sll(t8, key, 1);
3855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ addu(t8, a3, t8);
3856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ swc1(f0, MemOperand(t8, 0));
3857589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
38583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sll(t8, key, 2);
3859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ addu(t8, a3, t8);
3860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sdc1(f0, MemOperand(t8, 0));
3861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
38623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        __ EmitECMATruncate(t3, f0, f2, t2, t1, t5);
3863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
38643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        switch (elements_kind) {
3865589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_BYTE_ELEMENTS:
3866589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
38673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ srl(t8, key, 1);
38683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ addu(t8, a3, t8);
3869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            __ sb(t3, MemOperand(t8, 0));
3870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            break;
3871589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_SHORT_ELEMENTS:
3872589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
38733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ addu(t8, a3, key);
3874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            __ sh(t3, MemOperand(t8, 0));
3875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            break;
3876589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_INT_ELEMENTS:
3877589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_INT_ELEMENTS:
38783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ sll(t8, key, 1);
3879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            __ addu(t8, a3, t8);
3880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            __ sw(t3, MemOperand(t8, 0));
3881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            break;
3882589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_PIXEL_ELEMENTS:
3883589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_FLOAT_ELEMENTS:
3884589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_DOUBLE_ELEMENTS:
3885589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case FAST_ELEMENTS:
38863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          case FAST_SMI_ONLY_ELEMENTS:
3887589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case FAST_DOUBLE_ELEMENTS:
3888589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case DICTIONARY_ELEMENTS:
3889589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case NON_STRICT_ARGUMENTS_ELEMENTS:
3890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            UNREACHABLE();
3891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            break;
3892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
3893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
3894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Entry registers are intact, a0 holds the value
3896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // which is the return value.
38973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(v0, a0);
3898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // FPU is not available, do manual conversions.
3901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ lw(t3, FieldMemOperand(value, HeapNumber::kExponentOffset));
3903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ lw(t4, FieldMemOperand(value, HeapNumber::kMantissaOffset));
3904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3905589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
3906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Label done, nan_or_infinity_or_zero;
3907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        static const int kMantissaInHiWordShift =
3908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
3909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        static const int kMantissaInLoWordShift =
3911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            kBitsPerInt - kMantissaInHiWordShift;
3912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Test for all special exponent values: zeros, subnormal numbers, NaNs
3914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // and infinities. All these should be converted to 0.
3915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ li(t5, HeapNumber::kExponentMask);
3916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ and_(t6, t3, t5);
3917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&nan_or_infinity_or_zero, eq, t6, Operand(zero_reg));
3918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ xor_(t1, t6, t5);
3920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ li(t2, kBinary32ExponentMask);
39213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Movz(t6, t2, t1);  // Only if t6 is equal to t5.
3922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&nan_or_infinity_or_zero, eq, t6, Operand(t5));
3923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Rebias exponent.
3925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ srl(t6, t6, HeapNumber::kExponentShift);
3926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Addu(t6,
3927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                t6,
3928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                Operand(kBinary32ExponentBias - HeapNumber::kExponentBias));
3929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ li(t1, Operand(kBinary32MaxExponent));
3931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Slt(t1, t1, t6);
3932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ And(t2, t3, Operand(HeapNumber::kSignMask));
3933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Or(t2, t2, Operand(kBinary32ExponentMask));
39343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Movn(t3, t2, t1);  // Only if t6 is gt kBinary32MaxExponent.
3935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&done, gt, t6, Operand(kBinary32MaxExponent));
3936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Slt(t1, t6, Operand(kBinary32MinExponent));
3938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ And(t2, t3, Operand(HeapNumber::kSignMask));
39393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Movn(t3, t2, t1);  // Only if t6 is lt kBinary32MinExponent.
3940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&done, lt, t6, Operand(kBinary32MinExponent));
3941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ And(t7, t3, Operand(HeapNumber::kSignMask));
3943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ And(t3, t3, Operand(HeapNumber::kMantissaMask));
3944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sll(t3, t3, kMantissaInHiWordShift);
3945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ or_(t7, t7, t3);
3946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ srl(t4, t4, kMantissaInLoWordShift);
3947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ or_(t7, t7, t4);
3948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sll(t6, t6, kBinary32ExponentShift);
3949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ or_(t3, t7, t6);
3950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ bind(&done);
39523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sll(t9, key, 1);
3953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ addu(t9, a2, t9);
3954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sw(t3, MemOperand(t9, 0));
3955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Entry registers are intact, a0 holds the value which is the return
3957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // value.
39583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(v0, a0);
3959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Ret();
3960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ bind(&nan_or_infinity_or_zero);
3962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ And(t7, t3, Operand(HeapNumber::kSignMask));
3963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ And(t3, t3, Operand(HeapNumber::kMantissaMask));
3964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ or_(t6, t6, t7);
3965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sll(t3, t3, kMantissaInHiWordShift);
3966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ or_(t6, t6, t3);
3967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ srl(t4, t4, kMantissaInLoWordShift);
3968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ or_(t3, t6, t4);
3969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&done);
3970589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sll(t8, t0, 3);
3972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ addu(t8, a3, t8);
3973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // t8: effective address of destination element.
3974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sw(t4, MemOperand(t8, 0));
3975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sw(t3, MemOperand(t8, Register::kSizeInBytes));
39763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(v0, a0);
3977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Ret();
3978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
39793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        bool is_signed_type = IsElementTypeSigned(elements_kind);
3980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt;
3981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        int32_t min_value    = is_signed_type ? 0x80000000 : 0x00000000;
3982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Label done, sign;
3984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Test for all special exponent values: zeros, subnormal numbers, NaNs
3986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // and infinities. All these should be converted to 0.
3987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ li(t5, HeapNumber::kExponentMask);
3988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ and_(t6, t3, t5);
39893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Movz(t3, zero_reg, t6);  // Only if t6 is equal to zero.
3990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&done, eq, t6, Operand(zero_reg));
3991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ xor_(t2, t6, t5);
39933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Movz(t3, zero_reg, t2);  // Only if t6 is equal to t5.
3994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&done, eq, t6, Operand(t5));
3995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Unbias exponent.
3997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ srl(t6, t6, HeapNumber::kExponentShift);
3998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Subu(t6, t6, Operand(HeapNumber::kExponentBias));
3999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // If exponent is negative then result is 0.
4000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ slt(t2, t6, zero_reg);
40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Movn(t3, zero_reg, t2);  // Only if exponent is negative.
4002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&done, lt, t6, Operand(zero_reg));
4003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // If exponent is too big then result is minimal value.
4005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ slti(t1, t6, meaningfull_bits - 1);
4006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ li(t2, min_value);
40073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Movz(t3, t2, t1);  // Only if t6 is ge meaningfull_bits - 1.
4008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&done, ge, t6, Operand(meaningfull_bits - 1));
4009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ And(t5, t3, Operand(HeapNumber::kSignMask));
4011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ And(t3, t3, Operand(HeapNumber::kMantissaMask));
4012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Or(t3, t3, Operand(1u << HeapNumber::kMantissaBitsInTopWord));
4013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ li(t9, HeapNumber::kMantissaBitsInTopWord);
4015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ subu(t6, t9, t6);
4016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ slt(t1, t6, zero_reg);
4017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ srlv(t2, t3, t6);
40183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Movz(t3, t2, t1);  // Only if t6 is positive.
4019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Branch(&sign, ge, t6, Operand(zero_reg));
4020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ subu(t6, zero_reg, t6);
4022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sllv(t3, t3, t6);
4023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ li(t9, meaningfull_bits);
4024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ subu(t6, t9, t6);
4025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ srlv(t4, t4, t6);
4026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ or_(t3, t3, t4);
4027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ bind(&sign);
4029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ subu(t2, t3, zero_reg);
40303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Movz(t3, t2, t5);  // Only if t5 is zero.
4031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ bind(&done);
4033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Result is in t3.
4035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // This switch block should be exactly the same as above (FPU mode).
40363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        switch (elements_kind) {
4037589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_BYTE_ELEMENTS:
4038589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ srl(t8, key, 1);
40403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ addu(t8, a3, t8);
4041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            __ sb(t3, MemOperand(t8, 0));
4042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            break;
4043589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_SHORT_ELEMENTS:
4044589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
40453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ addu(t8, a3, key);
4046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            __ sh(t3, MemOperand(t8, 0));
4047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            break;
4048589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_INT_ELEMENTS:
4049589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_INT_ELEMENTS:
40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ sll(t8, key, 1);
4051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            __ addu(t8, a3, t8);
4052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            __ sw(t3, MemOperand(t8, 0));
4053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            break;
4054589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_PIXEL_ELEMENTS:
4055589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_FLOAT_ELEMENTS:
4056589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_DOUBLE_ELEMENTS:
4057589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case FAST_ELEMENTS:
40583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          case FAST_SMI_ONLY_ELEMENTS:
4059589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case FAST_DOUBLE_ELEMENTS:
4060589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case DICTIONARY_ELEMENTS:
4061589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case NON_STRICT_ARGUMENTS_ELEMENTS:
4062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            UNREACHABLE();
4063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            break;
4064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
4065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
4066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
4067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Slow case, key and receiver still in a0 and a1.
4070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&slow);
4071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(
4072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->counters()->keyed_load_external_array_slow(),
4073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      1, a2, a3);
4074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Entry registers are intact.
4075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ---------- S t a t e --------------
4076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
4077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0     : key
4078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1     : receiver
4079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
4080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> slow_ic =
4081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_Slow();
4082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(slow_ic, RelocInfo::CODE_TARGET);
4083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Miss case, call the runtime.
4085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
4086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ---------- S t a t e --------------
4088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
4089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0     : key
4090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1     : receiver
4091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
4092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
4094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
4096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
4100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
4101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
4102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : key
4103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : receiver
4104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
4105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic;
4106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
4108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
4109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
41113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfNotSmi(a0, &miss_force_generic, at, USE_DELAY_SLOT);
41123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The delay slot can be safely used here, a1 is an object pointer.
4113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array.
4115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset));
4116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AssertFastElements(a2);
4117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is within bounds.
4119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a3, FieldMemOperand(a2, FixedArray::kLengthOffset));
41203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(USE_DELAY_SLOT, &miss_force_generic, hs, a0, Operand(a3));
4121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the result and make sure it's not the hole.
4123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(a3, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4124589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
4125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize);
4126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(t0, t0, a3);
4127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(t0, MemOperand(t0));
4128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(t1, Heap::kTheHoleValueRootIndex);
4129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&miss_force_generic, eq, t0, Operand(t1));
41303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Ret(USE_DELAY_SLOT);
4131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(v0, t0);
4132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
41343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub =
41353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
41363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(stub, RelocInfo::CODE_TARGET);
4137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
41403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
41413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
41423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
41433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ra    : return address
41443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- a0    : key
41453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- a1    : receiver
41463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
41473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label miss_force_generic, slow_allocate_heapnumber;
41483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register key_reg = a0;
41503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register receiver_reg = a1;
41513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register elements_reg = a2;
41523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register heap_number_reg = a2;
41533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register indexed_double_offset = a3;
41543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register scratch = t0;
41553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register scratch2 = t1;
41563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register scratch3 = t2;
41573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register heap_number_map = t3;
41583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
41603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
41613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a smi.
41633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(key_reg, &miss_force_generic);
41643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the elements array.
41663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ lw(elements_reg,
41673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
41683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is within bounds.
41703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
41713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch));
41723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Load the upper word of the double in the fixed array and test for NaN.
41743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ sll(scratch2, key_reg, kDoubleSizeLog2 - kSmiTagSize);
41753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Addu(indexed_double_offset, elements_reg, Operand(scratch2));
41763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t upper_32_offset = FixedArray::kHeaderSize + sizeof(kHoleNanLower32);
41773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ lw(scratch, FieldMemOperand(indexed_double_offset, upper_32_offset));
41783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Branch(&miss_force_generic, eq, scratch, Operand(kHoleNanUpper32));
41793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Non-NaN. Allocate a new heap number and copy the double value into it.
41813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
41823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AllocateHeapNumber(heap_number_reg, scratch2, scratch3,
41833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        heap_number_map, &slow_allocate_heapnumber);
41843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Don't need to reload the upper 32 bits of the double, it's already in
41863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // scratch.
41873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ sw(scratch, FieldMemOperand(heap_number_reg,
41883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 HeapNumber::kExponentOffset));
41893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ lw(scratch, FieldMemOperand(indexed_double_offset,
41903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 FixedArray::kHeaderSize));
41913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ sw(scratch, FieldMemOperand(heap_number_reg,
41923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 HeapNumber::kMantissaOffset));
41933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(v0, heap_number_reg);
41953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
41963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow_allocate_heapnumber);
41983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
41993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
42003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(slow_ic, RelocInfo::CODE_TARGET);
42013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
42023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
42033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_ic =
42043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
42053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
42063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
42073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
42083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement(
42103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind elements_kind,
42133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
4214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
4215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0    : value
4216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1    : key
4217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2    : receiver
4218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra    : return address
4219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a3    : scratch
4220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a4    : scratch (elements)
4221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
42223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, transition_elements_kind, grow, slow;
42233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label finish_store, check_capacity;
4224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register value_reg = a0;
4226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register key_reg = a1;
4227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register receiver_reg = a2;
42283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = t0;
42293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register elements_reg = a3;
42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register length_reg = t1;
42313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch2 = t2;
4232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
4234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
4235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
42373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(key_reg, &miss_force_generic);
4238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
42393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
42403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotSmi(value_reg, &transition_elements_kind);
42413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
42425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
424385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Check that the key is within bounds.
42443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(elements_reg,
42453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
424685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (is_js_array) {
424785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    __ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4248592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  } else {
424985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4250592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
425185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Compare smis.
42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&grow, hs, key_reg, Operand(scratch));
42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch));
42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
425785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Make sure elements is a fast element array, not 'cow'.
42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(elements_reg,
42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              scratch,
42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Heap::kFixedArrayMapRootIndex,
42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              &miss_force_generic,
42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DONT_DO_SMI_CHECK);
426485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(scratch,
42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            elements_reg,
42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Operand(FixedArray::kHeaderSize - kHeapObjectTag));
42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize);
42733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(scratch, scratch, scratch2);
42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(value_reg, MemOperand(scratch));
42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(elements_kind == FAST_ELEMENTS);
42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(scratch,
42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            elements_reg,
42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Operand(FixedArray::kHeaderSize - kHeapObjectTag));
42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize);
42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(scratch, scratch, scratch2);
42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(value_reg, MemOperand(scratch));
42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(receiver_reg, value_reg);
42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(elements_kind == FAST_ELEMENTS);
42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWrite(elements_reg,  // Object.
42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   scratch,       // Address.
42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   receiver_reg,  // Value.
42893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   kRAHasNotBeenSaved,
42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   kDontSaveFPRegs);
42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // value_reg (a0) is preserved.
4293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Done.
4294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
4295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
4297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic =
4298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(ic_miss, RelocInfo::CODE_TARGET);
43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array by a single element if possible.
43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
43103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime.
43113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&miss_force_generic, ne, key_reg, Operand(scratch));
43123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
43143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
43153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(length_reg,
43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
43173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(elements_reg,
43183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
43193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex);
43203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&check_capacity, ne, elements_reg, Operand(at));
43213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
43233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, elements_reg, scratch, scratch2, &slow,
43243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          TAG_OBJECT);
43253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
43273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(scratch, FieldMemOperand(elements_reg, JSObject::kMapOffset));
43283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(scratch, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
43293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
43303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
43313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
43323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(scratch, FieldMemOperand(elements_reg, FixedArray::SizeFor(i)));
43333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
43343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Store the element at index zero.
43363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(value_reg, FieldMemOperand(elements_reg, FixedArray::SizeFor(0)));
43373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
43393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(elements_reg,
43403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
43413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg,
43423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch, kRAHasNotBeenSaved, kDontSaveFPRegs,
43433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
43443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
43463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(length_reg, Operand(Smi::FromInt(1)));
43473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
43483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Ret();
43493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
43513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for cow elements, in general they are not handled by this stub
43523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CheckMap(elements_reg,
43533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                scratch,
43543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Heap::kFixedCOWArrayMapRootIndex,
43553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &miss_force_generic,
43563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                DONT_DO_SMI_CHECK);
43573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
43593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&slow, hs, length_reg, Operand(scratch));
43603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
43623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(length_reg, length_reg, Operand(Smi::FromInt(1)));
43633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
43643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
43653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
43673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
43683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Jump(ic_slow, RelocInfo::CODE_TARGET);
43693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
43711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
43721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
43733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
43743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm,
43753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
43763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
43773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
43783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- a0    : value
43793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- a1    : key
43803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- a2    : receiver
43813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ra    : return address
43823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- a3    : scratch
43833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- t0    : scratch (elements_reg)
43843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- t1    : scratch (mantissa_reg)
43853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- t2    : scratch (exponent_reg)
43863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- t3    : scratch4
43873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
43883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, transition_elements_kind, grow, slow;
43893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label finish_store, check_capacity;
43903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register value_reg = a0;
43923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register key_reg = a1;
43933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register receiver_reg = a2;
43943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register elements_reg = a3;
43953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch1 = t0;
43963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch2 = t1;
43973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch3 = t2;
43983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register scratch4 = t3;
43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register length_reg = t3;
44003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
44013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
44023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
44033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(key_reg, &miss_force_generic);
44043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
44053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ lw(elements_reg,
44063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
44073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
44083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is within bounds.
44093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (is_js_array) {
44103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
44113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
44123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch1,
44133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
44143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
44153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compare smis, unsigned compare catches both negative and out-of-bound
44163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // indexes.
44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (grow_mode == ALLOW_JSARRAY_GROWTH) {
44183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&grow, hs, key_reg, Operand(scratch1));
441985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  } else {
44203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch1));
442185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
442285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
44233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
44243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreNumberToDoubleElements(value_reg,
44263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 key_reg,
44273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 receiver_reg,
44283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 elements_reg,
44293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch1,
44303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch2,
44313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch3,
44323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch4,
44333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 &transition_elements_kind);
44343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
443569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ Ret(USE_DELAY_SLOT);
443669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ mov(v0, value_reg);  // In delay slot.
44373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
44383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Handle store cache miss, replacing the ic with the generic stub.
44393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
44403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> ic =
44413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
44423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
44433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
44453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
44463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(ic_miss, RelocInfo::CODE_TARGET);
44473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
44493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array by a single element if possible.
44503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
44513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
44533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime.
44543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&miss_force_generic, ne, key_reg, Operand(scratch1));
44553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Transition on values that can't be stored in a FixedDoubleArray.
44573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label value_is_smi;
44583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(value_reg, &value_is_smi);
44593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
44603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
44613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&transition_elements_kind, ne, scratch1, Operand(at));
44623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&value_is_smi);
44633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
44653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
44663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(length_reg,
44673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
44683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(elements_reg,
44693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
44703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex);
44713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&check_capacity, ne, elements_reg, Operand(at));
44723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
44743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, elements_reg, scratch1, scratch2, &slow,
44753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          TAG_OBJECT);
44763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Initialize the new FixedDoubleArray. Leave elements unitialized for
44783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // efficiency, they are guaranteed to be initialized before use.
44793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(scratch1, Heap::kFixedDoubleArrayMapRootIndex);
44803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(scratch1, FieldMemOperand(elements_reg, JSObject::kMapOffset));
44813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(scratch1, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
44823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(scratch1,
44833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset));
44843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
44863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(elements_reg,
44873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
44883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg,
44893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch1, kRAHasNotBeenSaved, kDontSaveFPRegs,
44903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
44913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
44933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(length_reg, Operand(Smi::FromInt(1)));
44943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
44959413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch    __ lw(elements_reg,
44969413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch          FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
44973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
44983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
45003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
45013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch1,
45023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset));
45033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&slow, hs, length_reg, Operand(scratch1));
45043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
45063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(length_reg, length_reg, Operand(Smi::FromInt(1)));
45073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
45083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
45093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
45113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
45123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Jump(ic_slow, RelocInfo::CODE_TARGET);
45133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
45143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
45153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
45163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
45173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef __
45183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
45193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} }  // namespace v8::internal
45203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_MIPS
4522