stub-cache-arm.cc revision 8f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7
13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_ARM)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h"
338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm)
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void ProbeTable(Isolate* isolate,
4344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                       MacroAssembler* masm,
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Code::Flags flags,
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       StubCache::Table table,
463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register receiver,
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Register name,
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       // Number of the cache entry, not scaled.
493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                       Register offset,
503e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                       Register scratch,
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register scratch2,
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register offset_scratch) {
5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference map_offset(isolate->stub_cache()->map_reference(table));
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
573e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address());
583e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  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());
603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Check the relative positions of the address fields.
623e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(value_off_addr > key_off_addr);
633e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT((value_off_addr - key_off_addr) % 4 == 0);
643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  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));
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
693e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  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  __ add(offset_scratch, offset, Operand(offset, LSL, 1));
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Calculate the base address of the entry.
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(base_addr, Operand(key_offset));
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(base_addr, base_addr, Operand(offset_scratch, LSL, kPointerSizeLog2));
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the key in the entry matches the name.
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(ip, MemOperand(base_addr, 0));
826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(name, ip);
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check the map matches.
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(ip, MemOperand(base_addr, map_off_addr - key_off_addr));
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset));
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(ip, scratch2);
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(ne, &miss);
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the code entry from the cache.
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register code = scratch2;
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scratch2 = no_reg;
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(code, MemOperand(base_addr, value_off_addr - key_off_addr));
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 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  __ ldr(flags_reg, FieldMemOperand(code, Code::kFlagsOffset));
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // It's a nice optimization if this constant is encodable in the bic insn.
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint32_t mask = Code::kFlagsNotUsedInLookup;
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(__ ImmediateFitsAddrMode1Instruction(mask));
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bic(flags_reg, flags_reg, Operand(mask));
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Using cmn and the negative instead of cmp means we can use movw.
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (flags < 0) {
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmn(flags_reg, Operand(-flags));
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(flags_reg, Operand(flags));
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&miss);
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&miss);
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the first instruction in the code stub.
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(pc, code, Operand(Code::kHeaderSize - kHeapObjectTag));
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1243e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Miss: fall through.
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Helper function used to check that the dictionary doesn't contain
1303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// the property. This function may return false negatives, so miss_label
1313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// must always call a backup property check that is complete.
1323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// This function is safe to call if the receiver has fast properties.
1333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Name must be a symbol and receiver must be a heap object.
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* miss_label,
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register receiver,
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Handle<String> name,
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register scratch0,
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register scratch1) {
1403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(name->IsSymbol());
14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
14244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
14344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
1443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label done;
1463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const int kInterceptorOrAccessCheckNeededMask =
1483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
1493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Bail out if the receiver has a named interceptor or requires access checks.
1513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register map = scratch1;
1523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
1533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
1543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
1553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ b(ne, miss_label);
1563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check that receiver is a JSObject.
1583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
1593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE));
1603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ b(lt, miss_label);
1613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Load properties array.
1633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register properties = scratch0;
1643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
1653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check that the properties array is a dictionary.
1663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset));
1673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register tmp = properties;
1683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
1693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ cmp(map, tmp);
1703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ b(ne, miss_label);
1713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Restore the temporarily used register.
1733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
1743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringDictionaryLookupStub::GenerateNegativeLookup(masm,
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     miss_label,
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     &done,
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     receiver,
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     properties,
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     name,
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     scratch1);
1833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ bind(&done);
18444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
1853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
1863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm,
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Code::Flags flags,
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register receiver,
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register name,
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register scratch,
1933e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                              Register extra,
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register extra2,
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register extra3) {
19644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = masm->isolate();
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Make sure that code is valid. The multiplying code relies on the
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // entry size being 12.
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(sizeof(Entry) == 12);
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the flags does not name a specific type.
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that there are no register conflicts.
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(receiver));
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(name));
2093e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra.is(receiver));
2103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra.is(name));
2113e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra.is(scratch));
2123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra2.is(receiver));
2133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra2.is(name));
2143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra2.is(scratch));
2153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra2.is(extra));
2163e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
2173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Check scratch, extra and extra2 registers are valid.
2183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!scratch.is(no_reg));
2193e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra.is(no_reg));
2203e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra2.is(no_reg));
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!extra3.is(no_reg));
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Counters* counters = masm->isolate()->counters();
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1,
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      extra2, extra3);
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, &miss);
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the map of the receiver and compute the hash.
231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset));
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(scratch, scratch, Operand(ip));
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint32_t mask = kPrimaryTableSize - 1;
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We shift out the last two bits because they are not part of the hash and
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // they are always 01 for maps.
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(scratch, Operand(scratch, LSR, kHeapObjectTagSize));
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Mask down the eor argument to the minimum to keep the immediate
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ARM-encodable.
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ eor(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask));
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Prefer and_ to ubfx here because ubfx takes 2 cycles.
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ and_(scratch, scratch, Operand(mask));
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the primary table.
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ProbeTable(isolate,
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             masm,
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             flags,
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             kPrimary,
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             receiver,
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             name,
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             scratch,
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             extra,
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             extra2,
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             extra3);
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Primary miss: Compute hash for secondary probe.
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(scratch, scratch, Operand(name, LSR, kHeapObjectTagSize));
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint32_t mask2 = kSecondaryTableSize - 1;
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask2));
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ and_(scratch, scratch, Operand(mask2));
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the secondary table.
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ProbeTable(isolate,
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             masm,
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             flags,
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             kSecondary,
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             receiver,
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             name,
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             scratch,
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             extra,
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             extra2,
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             extra3);
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache miss: Fall-through and let caller handle the miss by
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // entering the runtime system.
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1,
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      extra2, extra3);
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       int index,
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       Register prototype) {
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global or builtins object from the current context.
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context from the global or builtins object.
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype,
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset));
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the function from the global context.
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index)));
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map.  The global functions all have initial maps.
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype,
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the prototype from the initial map.
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int index,
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register prototype,
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* miss) {
30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = masm->isolate();
3060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check we're still in the same context.
3070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Move(ip, isolate->global());
3090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ cmp(prototype, ip);
3100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ b(ne, miss);
3117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get the global function with the given index.
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSFunction> function(
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      JSFunction::cast(isolate->global_context()->get(index)));
3147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load its initial map. The global functions all have initial maps.
3157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Move(prototype, Handle<Map>(function->initial_map()));
3167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load the prototype from the initial map.
3177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
3187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
3197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load a fast property out of a holder object (src). In-object properties
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are loaded directly otherwise the property is loaded from the properties
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// fixed array.
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Register dst,
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Register src,
3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Handle<JSObject> holder,
3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            int index) {
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust for the number of properties stored in the holder.
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index -= holder->map()->inobject_properties();
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the property straight out of the holder.
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = holder->map()->instance_size() + (index * kPointerSize);
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(dst, FieldMemOperand(src, offset));
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate the offset into the properties array.
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(dst, FieldMemOperand(dst, offset));
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch,
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss_label) {
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
3493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss_label);
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a JS array.
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, miss_label);
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load length directly from the JS array.
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Generate code to check if an object is a string.  If the object is a
362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// heap object, its map's instance type is left in the scratch1 register.
363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// If this is not needed, scratch1 and scratch2 may be the same register.
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm,
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register receiver,
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register scratch1,
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register scratch2,
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* smi,
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* non_string_object) {
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
3713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, smi);
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a string.
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The cast is to resolve the overload for the argument of 0x0.
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, non_string_object);
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to load the length from a string object and return the length.
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the receiver object is not a string or a wrapped string object the
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// execution continues at the miss label. The register containing the
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// receiver is potentially clobbered.
387402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register receiver,
389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register scratch1,
390402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register scratch2,
3911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                            Label* miss,
3921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                            bool support_wrappers) {
393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label check_wrapper;
394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the object is a string leaving the instance type in the
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch1 register.
3971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateStringCheck(masm, receiver, scratch1, scratch2, miss,
3981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      support_wrappers ? &check_wrapper : miss);
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load length directly from the string.
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (support_wrappers) {
4051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check if the object is a JSValue wrapper.
4061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&check_wrapper);
4071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmp(scratch1, Operand(JS_VALUE_TYPE));
4081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(ne, miss);
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Unwrap the value and check if the wrapped value is a string.
4111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ldr(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset));
4121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss);
4131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ldr(r0, FieldMemOperand(scratch1, String::kLengthOffset));
4141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Ret();
4151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register receiver,
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register scratch1,
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register scratch2,
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Label* miss_label) {
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, scratch1);
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate StoreField code, value is passed in r0 register.
431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// When leaving generated code after success, the receiver_reg and name_reg
432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// may be clobbered.  Upon branch to miss_label, the receiver and name
433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// registers have their original values.
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm,
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<JSObject> object,
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      int index,
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<Map> transition,
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register receiver_reg,
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register name_reg,
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch,
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* miss_label) {
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0 : value
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label exit;
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the map of the object hasn't changed.
4468f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
4478f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch                                             : REQUIRE_EXACT_MAP;
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(receiver_reg, scratch, Handle<Map>(object->map()), miss_label,
4498f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch              DO_SMI_CHECK, mode);
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform map transition for the receiver if necessary.
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) {
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The properties must be extended before we can store the value.
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We jump to a runtime call that extends the properties array.
464402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(receiver_reg);
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r2, Operand(transition));
4666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ Push(r2, r0);
4676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ TailCallExternalReference(
46844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
46944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          masm->isolate()),
47044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        3,
47144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        1);
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!transition.is_null()) {
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the map of the object; no write barrier updating is
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // needed because the map is never in new space.
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ip, Operand(transition));
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust for the number of properties stored in the object. Even in the
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // face of a transition we can use the old map here because the size of the
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object and the number of in-object properties is not going to change.
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index -= object->map()->inobject_properties();
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set the property straight into the object.
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = object->map()->instance_size() + (index * kPointerSize);
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r0, FieldMemOperand(receiver_reg, offset));
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Skip updating write barrier if storing a smi.
4933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r0, &exit);
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
4969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    // Pass the now unused name_reg as a scratch register.
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(name_reg, r0);
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(receiver_reg,
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        offset,
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        name_reg,
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch,
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kLRHasNotBeenSaved,
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs);
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Write to the properties array.
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the properties array
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r0, FieldMemOperand(scratch, offset));
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Skip updating write barrier if storing a smi.
5123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r0, &exit);
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Ok to clobber receiver_reg and name_reg, since we return.
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(name_reg, r0);
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(scratch,
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        offset,
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        name_reg,
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        receiver_reg,
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kLRHasNotBeenSaved,
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs);
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the value (register r0).
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&exit);
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code = (kind == Code::LOAD_IC)
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? masm->isolate()->builtins()->LoadIC_Miss()
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : masm->isolate()->builtins()->KeyedLoadIC_Miss();
5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(code, RelocInfo::CODE_TARGET);
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkestatic void GenerateCallFunction(MacroAssembler* masm,
5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Handle<Object> object,
5424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                 const ParameterCount& arguments,
543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Label* miss,
544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Code::ExtraICState extra_ic_state) {
5454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // ----------- S t a t e -------------
5464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- r0: receiver
5474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- r1: function to call
5484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // -----------------------------------
5494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Check that the function really is a function.
5511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r1, miss);
552402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
5534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ b(ne, miss);
5544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Patch the receiver on the stack with the global proxy if
5564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // necessary.
5574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (object->IsGlobalObject()) {
5584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
5594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize));
5604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
5614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Invoke the function.
563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind);
5674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
5684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkestatic void PushInterceptorArguments(MacroAssembler* masm,
5714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                     Register receiver,
5724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                     Register holder,
5734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                     Register name,
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<JSObject> holder_obj) {
5754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(name);
5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
5773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor));
5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register scratch = name;
5793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(scratch, Operand(interceptor));
5804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(scratch);
5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(receiver);
5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(holder);
5834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ ldr(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset));
5844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(scratch);
5854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
5864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void CompileCallLoadPropertyWithInterceptor(
5893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register receiver,
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register holder,
5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register name,
5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder_obj) {
5944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
5954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ExternalReference ref =
59744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
59844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        masm->isolate());
5994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ mov(r0, Operand(5));
6004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ mov(r1, Operand(ref));
6014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
6024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CEntryStub stub(1);
6034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ CallStub(&stub);
6044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
6054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
6063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic const int kFastApiCallArguments = 3;
6084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
6096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Reserves space for the extra arguments to FastHandleApiCall in the
6106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// caller's frame.
6116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block//
6121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// These arguments are set by CheckPrototypes and GenerateFastApiDirectCall.
6136ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void ReserveSpaceForFastApiCall(MacroAssembler* masm,
6146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                       Register scratch) {
6156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(scratch, Operand(Smi::FromInt(0)));
6161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = 0; i < kFastApiCallArguments; i++) {
6171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ push(scratch);
6181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
6196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Undoes the effects of ReserveSpaceForFastApiCall.
6236ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void FreeSpaceForFastApiCall(MacroAssembler* masm) {
6241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ Drop(kFastApiCallArguments);
6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateFastApiDirectCall(MacroAssembler* masm,
6291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      const CallOptimization& optimization,
6301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      int argc) {
6311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
6321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- sp[0]              : holder (set by CheckPrototypes)
6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- sp[4]              : callee JS function
6341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- sp[8]              : call data
6353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- sp[12]             : last JS argument
6361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- ...
6373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- sp[(argc + 3) * 4] : first JS argument
6381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- sp[(argc + 4) * 4] : receiver
6391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
6406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the function and setup the context.
6413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSFunction> function = optimization.constant_function();
6423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(r5, function);
6438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset));
6446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Pass the additional arguments FastHandleApiCall expects.
6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> call_data(api_call_info->data());
6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (masm->isolate()->heap()->InNewSpace(*call_data)) {
6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(r0, api_call_info);
6508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset));
6516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(r6, call_data);
6536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store JS function and call data.
6551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ stm(ib, sp, r5.bit() | r6.bit());
6566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r2 points to call data as expected by Arguments
6581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // (refer to layout above).
6591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ add(r2, sp, Operand(2 * kPointerSize));
6606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
66185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  const int kApiStackSpace = 4;
6623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope frame_scope(masm, StackFrame::MANUAL);
6641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ EnterExitFrame(false, kApiStackSpace);
6651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r0 = v8::Arguments&
6671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Arguments is after the return address.
6681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ add(r0, sp, Operand(1 * kPointerSize));
6691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // v8::Arguments::implicit_args = data
6701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ str(r2, MemOperand(r0, 0 * kPointerSize));
6711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // v8::Arguments::values = last argument
6721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ add(ip, r2, Operand(argc * kPointerSize));
6731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ str(ip, MemOperand(r0, 1 * kPointerSize));
6741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // v8::Arguments::length_ = argc
6751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ mov(ip, Operand(argc));
6761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ str(ip, MemOperand(r0, 2 * kPointerSize));
6771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // v8::Arguments::is_construct_call = 0
6781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ mov(ip, Operand(0));
6791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ str(ip, MemOperand(r0, 3 * kPointerSize));
6801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const int kStackUnwindSpace = argc + kFastApiCallArguments + 1;
6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address function_address = v8::ToCData<Address>(api_call_info->callback());
6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ApiFunction fun(function_address);
68444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference ref = ExternalReference(&fun,
68544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            ExternalReference::DIRECT_API_CALL,
68644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                            masm->isolate());
6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AllowExternalCallThatCantCauseGC scope(masm);
6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallApiFunctionAndReturn(ref, kStackUnwindSpace);
6906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6936ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CallInterceptorCompiler BASE_EMBEDDED {
6946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
6956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallInterceptorCompiler(StubCompiler* stub_compiler,
6966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          const ParameterCount& arguments,
697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          Register name,
698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          Code::ExtraICState extra_ic_state)
6996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : stub_compiler_(stub_compiler),
7006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        arguments_(arguments),
701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        name_(name),
702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        extra_ic_state_(extra_ic_state) {}
7036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Compile(MacroAssembler* masm,
7053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Handle<JSObject> object,
7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Handle<JSObject> holder,
7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Handle<String> name,
7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               LookupResult* lookup,
7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register receiver,
7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register scratch1,
7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register scratch2,
7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register scratch3,
7133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Label* miss) {
7146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(holder->HasNamedInterceptor());
7156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
7166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Check that the receiver isn't a smi.
7181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ JumpIfSmi(receiver, miss);
7196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CallOptimization optimization(lookup);
7206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (optimization.is_constant_call()) {
7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       holder, lookup, name, optimization, miss);
7236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     name, holder, miss);
7266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CompileCacheable(MacroAssembler* masm,
7313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Handle<JSObject> object,
7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register receiver,
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch1,
7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch2,
7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch3,
7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Handle<JSObject> interceptor_holder,
7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        LookupResult* lookup,
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Handle<String> name,
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        const CallOptimization& optimization,
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Label* miss_label) {
7416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(optimization.is_constant_call());
7426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!lookup->holder()->IsGlobalObject());
74344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Counters* counters = masm->isolate()->counters();
7446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int depth1 = kInvalidProtoDepth;
7456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int depth2 = kInvalidProtoDepth;
7466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool can_do_fast_api_call = false;
7476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (optimization.is_simple_api_call() &&
7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        !lookup->holder()->IsGlobalObject()) {
7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      depth1 = optimization.GetPrototypeDepthOfExpectedType(
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          object, interceptor_holder);
7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (depth1 == kInvalidProtoDepth) {
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        depth2 = optimization.GetPrototypeDepthOfExpectedType(
7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            interceptor_holder, Handle<JSObject>(lookup->holder()));
7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      can_do_fast_api_call =
7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
7576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
75944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ IncrementCounter(counters->call_const_interceptor(), 1,
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch1, scratch2);
7616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1,
7646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          scratch1, scratch2);
7656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ReserveSpaceForFastApiCall(masm, scratch1);
7666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Check that the maps from receiver to interceptor's holder
769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // haven't changed and thus we can invoke interceptor.
7706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label miss_cleanup;
7716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register holder =
7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        scratch1, scratch2, scratch3,
7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        name, depth1, miss);
7766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke an interceptor and if it provides a value,
778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // branch to |regular_invoke|.
7796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label regular_invoke;
780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2,
7816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        &regular_invoke);
7826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Interceptor returned nothing for this property.  Try to use cached
784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // constant function.
7856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Check that the maps from interceptor's holder to constant function's
787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // holder haven't changed and thus we can use cached constant function.
7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (*interceptor_holder != lookup->holder()) {
7897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<JSObject>(lookup->holder()),
7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      scratch1, scratch2, scratch3,
7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      name, depth2, miss);
7937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
7947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // CheckPrototypes has a side effect of fetching a 'holder'
7957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // for API (object which is instanceof for the signature).  It's
7967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // safe to omit it here, as if present, it should be fetched
7977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // by the previous CheckPrototypes.
7987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(depth2 == kInvalidProtoDepth);
7997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke function.
8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateFastApiDirectCall(masm, optimization, arguments_.immediate());
8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          ? CALL_AS_FUNCTION
807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          : CALL_AS_METHOD;
8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ InvokeFunction(optimization.constant_function(), arguments_,
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        JUMP_FUNCTION, NullCallWrapper(), call_kind);
8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Deferred code for fast API call case---clean preallocated space.
8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ bind(&miss_cleanup);
8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FreeSpaceForFastApiCall(masm);
8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ b(miss_label);
8176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke a regular function.
8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ bind(&regular_invoke);
8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FreeSpaceForFastApiCall(masm);
8236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void CompileRegular(MacroAssembler* masm,
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Handle<JSObject> object,
8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Register receiver,
8296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Register scratch1,
8306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Register scratch2,
8313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                      Register scratch3,
8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Handle<String> name,
8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Handle<JSObject> interceptor_holder,
8346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Label* miss_label) {
8356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register holder =
836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        scratch1, scratch2, scratch3,
8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        name, miss_label);
8396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Call a runtime function to load the interceptor property.
8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
8426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Save the name_ register across the call.
8436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ push(name_);
8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallExternalReference(
84644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
84744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          masm->isolate()),
84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        5);
8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Restore the name_ register.
8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(name_);
8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Leave the internal frame.
8526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void LoadWithInterceptor(MacroAssembler* masm,
8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register receiver,
8566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register holder,
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Handle<JSObject> holder_obj,
8586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register scratch,
8596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Label* interceptor_succeeded) {
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FrameScope scope(masm, StackFrame::INTERNAL);
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Push(holder, name_);
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCallLoadPropertyWithInterceptor(masm,
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             receiver,
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder,
8663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             name_,
8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder_obj);
8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(name_);  // Restore the name.
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(receiver);  // Restore the holder.
8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // If interceptor returns no-result sentinel, call the constant function.
8726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
8736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ cmp(r0, scratch);
8746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ b(ne, interceptor_succeeded);
8756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StubCompiler* stub_compiler_;
8786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const ParameterCount& arguments_;
8796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register name_;
880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Code::ExtraICState extra_ic_state_;
8816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
8826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generate code to check that a global property cell is empty. Create
8856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the property cell at compilation time if no cell exists for the
8866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property.
8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCell(MacroAssembler* masm,
8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<GlobalObject> global,
8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<String> name,
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Register scratch,
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Label* miss) {
8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSGlobalPropertyCell> cell =
8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GlobalObject::EnsurePropertyCell(global, name);
8946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(cell->value()->IsTheHole());
8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(scratch, Operand(cell));
8966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(scratch,
8976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block         FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
8986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
8996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(scratch, ip);
9006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ b(ne, miss);
9016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
9026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Calls GenerateCheckPropertyCell for each global object in the prototype chain
905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from object to (but not including) holder.
9063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCells(MacroAssembler* masm,
9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> object,
9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> holder,
9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<String> name,
9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register scratch,
9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Label* miss) {
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> current = object;
9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!current.is_identical_to(holder)) {
914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (current->IsGlobalObject()) {
9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateCheckPropertyCell(masm,
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Handle<GlobalObject>::cast(current),
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                name,
9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                scratch,
9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                miss);
920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    current = Handle<JSObject>(JSObject::cast(current->GetPrototype()));
922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
9261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Convert and store int passed in register ival to IEEE 754 single precision
9271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// floating point value at memory location (dst + 4 * wordoffset)
9281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// If VFP3 is available use it for conversion.
9291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void StoreIntAsFloat(MacroAssembler* masm,
9301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                            Register dst,
9311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                            Register wordoffset,
9321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                            Register ival,
9331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                            Register fval,
9341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                            Register scratch1,
9351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                            Register scratch2) {
9368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(VFP3)) {
9371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CpuFeatures::Scope scope(VFP3);
9381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vmov(s0, ival);
9391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ add(scratch1, dst, Operand(wordoffset, LSL, 2));
9401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vcvt_f32_s32(s0, s0);
9411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vstr(s0, scratch1, 0);
9421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
9431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Label not_special, done;
9441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Move sign bit from source to destination.  This works because the sign
9451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // bit in the exponent word of the double has the same position and polarity
9461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // as the 2's complement sign bit in a Smi.
9471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(kBinary32SignMask == 0x80000000u);
9481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ and_(fval, ival, Operand(kBinary32SignMask), SetCC);
9501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Negate value if it is negative.
9511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ rsb(ival, ival, Operand(0, RelocInfo::NONE), LeaveCC, ne);
9521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // We have -1, 0 or 1, which we treat specially. Register ival contains
9541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // absolute value: it is either equal to 1 (special case of -1 and 1),
9551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // greater than 1 (not a special case) or less than 1 (special case of 0).
9561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmp(ival, Operand(1));
9571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(gt, &not_special);
9581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For 1 or -1 we need to or in the 0 exponent (biased).
9601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    static const uint32_t exponent_word_for_1 =
9611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        kBinary32ExponentBias << kBinary32ExponentShift;
9621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ orr(fval, fval, Operand(exponent_word_for_1), LeaveCC, eq);
9641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(&done);
9651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&not_special);
9671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Count leading zeros.
9681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Gets the wrong answer for 0, but we already checked for that case above.
9691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Register zeros = scratch2;
9701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ CountLeadingZeros(zeros, ival, scratch1);
9711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Compute exponent and or it into the exponent register.
9731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ rsb(scratch1,
9741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           zeros,
9751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           Operand((kBitsPerInt - 1) + kBinary32ExponentBias));
9761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ orr(fval,
9781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           fval,
9791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           Operand(scratch1, LSL, kBinary32ExponentShift));
9801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Shift up the source chopping the top bit off.
9821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ add(zeros, zeros, Operand(1));
9831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // This wouldn't work for 1 and -1 as the shift would be 32 which means 0.
9841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(ival, Operand(ival, LSL, zeros));
9851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // And the top (top 20 bits).
9861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ orr(fval,
9871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           fval,
9881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           Operand(ival, LSR, kBitsPerInt - kBinary32MantissaBits));
9891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&done);
9911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ str(fval, MemOperand(dst, wordoffset, LSL, 2));
9921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
9931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
9941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Convert unsigned integer with specified number of leading zeroes in binary
9971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// representation to IEEE 754 double.
9981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Integer to convert is passed in register hiword.
9991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Resulting double is returned in registers hiword:loword.
10001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// This functions does not work correctly for 0.
10011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void GenerateUInt2Double(MacroAssembler* masm,
10021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                Register hiword,
10031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                Register loword,
10041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                Register scratch,
10051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                int leading_zeroes) {
10061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int meaningful_bits = kBitsPerInt - leading_zeroes - 1;
10071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int biased_exponent = HeapNumber::kExponentBias + meaningful_bits;
10081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
10091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int mantissa_shift_for_hi_word =
10101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      meaningful_bits - HeapNumber::kMantissaBitsInTopWord;
10111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
10121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int mantissa_shift_for_lo_word =
10131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      kBitsPerInt - mantissa_shift_for_hi_word;
10141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
10151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ mov(scratch, Operand(biased_exponent << HeapNumber::kExponentShift));
10161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (mantissa_shift_for_hi_word > 0) {
10171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(loword, Operand(hiword, LSL, mantissa_shift_for_lo_word));
10181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ orr(hiword, scratch, Operand(hiword, LSR, mantissa_shift_for_hi_word));
10191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
10201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(loword, Operand(0, RelocInfo::NONE));
10211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ orr(hiword, scratch, Operand(hiword, LSL, mantissa_shift_for_hi_word));
10221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
10231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
10241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // If least significant bit of biased exponent was not 1 it was corrupted
10251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // by most significant bit of mantissa so we should fix that.
10261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!(biased_exponent & 1)) {
10271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bic(hiword, hiword, Operand(1 << HeapNumber::kExponentShift));
10281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
10291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
10301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm())
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister StubCompiler::CheckPrototypes(Handle<JSObject> object,
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register object_reg,
10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> holder,
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register holder_reg,
10403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Register scratch1,
10413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Register scratch2,
10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<String> name,
1043402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                       int save_at_depth,
10443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Label* miss) {
10453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Make sure there's no overlap between holder and object registers.
10463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
10473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
10483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch         && !scratch2.is(scratch1));
10493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
10503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Keep track of the current object in register reg.
10513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register reg = object_reg;
10523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  int depth = 0;
10533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
10543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (save_at_depth == depth) {
10553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ str(reg, MemOperand(sp));
10563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
10573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
10583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check the maps in the prototype chain.
10593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Traverse the prototype chain from the object and do map checks.
10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> current = object;
10613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!current.is_identical_to(holder)) {
10623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ++depth;
10633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
10643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Only global objects and objects that do not require access
10653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // checks are allowed in stubs.
10663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
10673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
10683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> prototype(JSObject::cast(current->GetPrototype()));
10693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    if (!current->HasFastProperties() &&
10703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        !current->IsJSGlobalObject() &&
10713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        !current->IsJSGlobalProxy()) {
10723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      if (!name->IsSymbol()) {
10733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        name = factory()->LookupSymbol(name);
10743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      }
10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(current->property_dictionary()->FindEntry(*name) ==
10763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch             StringDictionary::kNotFound);
10773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       scratch1, scratch2);
1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reg = holder_reg;  // From now on the object will be in holder_reg.
10833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
10853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Map> current_map(current->map());
10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK,
10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  ALLOW_ELEMENT_TRANSITION_MAPS);
108885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
10893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check access rights to the global object.  This has to happen after
10903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the map check so that we know that the object is actually a global
10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // object.
10923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      if (current->IsJSGlobalProxy()) {
10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckAccessGlobalProxy(reg, scratch2, miss);
10943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      }
10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reg = holder_reg;  // From now on the object will be in holder_reg.
10963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
10973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (heap()->InNewSpace(*prototype)) {
10983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The prototype is in new space; we cannot store a reference to it
10993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // in the code.  Load it from the map.
11003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
11013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
11023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The prototype is in old space; load it directly.
11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(reg, Operand(prototype));
11043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      }
11053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    }
11063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
11073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    if (save_at_depth == depth) {
11083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ str(reg, MemOperand(sp));
11093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    }
11103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
11113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Go to the next object in the prototype chain.
11123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    current = prototype;
11133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
11143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1115592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Log the check depth.
1116592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1));
1117592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check the holder map.
11193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(reg, scratch1, Handle<Map>(current->map()), miss,
11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Perform security check for access to the global object.
1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (holder->IsJSGlobalProxy()) {
11253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ CheckAccessGlobalProxy(reg, scratch1, miss);
11263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If we've skipped any global objects, it's not enough to verify that
11293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // their maps haven't changed.  We also need to check that the property
11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // cell for the property is still empty.
11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1133402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Return the register containing the holder.
11343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  return reg;
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadField(Handle<JSObject> object,
11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<JSObject> holder,
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register receiver,
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch1,
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch2,
11433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                     Register scratch3,
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     int index,
11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<String> name,
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Label* miss) {
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
11483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
11513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = CheckPrototypes(
11523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), r0, reg, holder, index);
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSObject> holder,
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register receiver,
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch1,
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch2,
11633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                        Register scratch3,
11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSFunction> value,
11653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<String> name,
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* miss) {
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
11683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(
11723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the constant value.
11753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(r0, value);
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSObject> holder,
11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register receiver,
11833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register name_reg,
11843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch1,
11853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch2,
11863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch3,
11873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<AccessorInfo> callback,
11883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<String> name,
11893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Label* miss) {
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
11913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = CheckPrototypes(object, receiver, holder, scratch1,
11953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch2, scratch3, name, miss);
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Build AccessorInfo::args_ list on the stack and push property name below
1198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the exit frame to make GC aware of them and store pointers to them.
1199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(receiver);
1200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ mov(scratch2, sp);  // scratch2 = AccessorInfo::args_
12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (heap()->InNewSpace(callback->data())) {
12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(scratch3, callback);
1203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ ldr(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset));
1204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Move(scratch3, Handle<Object>(callback->data()));
1206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ Push(reg, scratch3, name_reg);
1208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ mov(r0, sp);  // r0 = Handle<String>
1209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const int kApiStackSpace = 1;
12113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope frame_scope(masm(), StackFrame::MANUAL);
1212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ EnterExitFrame(false, kApiStackSpace);
12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Create AccessorInfo instance on the stack above the exit frame with
12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // scratch2 (internal::Object** args_) as the data.
1216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ str(scratch2, MemOperand(sp, 1 * kPointerSize));
1217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ add(r1, sp, Operand(1 * kPointerSize));  // r1 = AccessorInfo&
1218e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const int kStackUnwindSpace = 4;
12203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address getter_address = v8::ToCData<Address>(callback->getter());
12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ApiFunction fun(getter_address);
1222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ExternalReference ref =
122344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(&fun,
122444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        ExternalReference::DIRECT_GETTER_CALL,
122544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        masm()->isolate());
12263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallApiFunctionAndReturn(ref, kStackUnwindSpace);
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Handle<JSObject> interceptor_holder,
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           LookupResult* lookup,
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register name_reg,
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch1,
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch2,
12373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                           Register scratch3,
12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Handle<String> name,
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss) {
12407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(interceptor_holder->HasNamedInterceptor());
12417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
12427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the receiver isn't a smi.
12441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(receiver, miss);
12457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // So far the most popular follow ups for interceptor loads are FIELD
12477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // and CALLBACKS, so inline only them, other cases may be added
12487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // later.
12497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  bool compile_followup_inline = false;
12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (lookup->IsFound() && lookup->IsCacheable()) {
12517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == FIELD) {
12527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      compile_followup_inline = true;
12537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else if (lookup->type() == CALLBACKS &&
12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               lookup->GetCallbackObject()->IsAccessorInfo()) {
12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      compile_followup_inline =
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL;
12577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
12587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
12597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (compile_followup_inline) {
12617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Compile the interceptor call, followed by inline code to load the
12627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // property from further up the prototype chain if the call fails.
12637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps haven't changed.
12647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
12653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          scratch1, scratch2, scratch3,
12663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          name, miss);
12677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
12687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Save necessary data before invoking an interceptor.
12707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Requires a frame to make GC aware of pushed pointers.
12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FrameScope frame_scope(masm(), StackFrame::INTERNAL);
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // CALLBACKS case needs a receiver to be passed into C++ callback.
12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Push(receiver, holder_reg, name_reg);
12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Push(holder_reg, name_reg);
12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Invoke an interceptor.  Note: map checks from receiver to
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // interceptor's holder has been compiled before (see a caller
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // of this method.)
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCallLoadPropertyWithInterceptor(masm(),
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             receiver,
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder_reg,
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             name_reg,
12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             interceptor_holder);
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if interceptor provided a value for property.  If it's
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the case, return immediately.
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label interceptor_failed;
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex);
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(r0, scratch1);
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ b(eq, &interceptor_failed);
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      frame_scope.GenerateLeaveFrame();
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Ret();
129585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&interceptor_failed);
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(name_reg);
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(holder_reg);
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ pop(receiver);
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Leave the internal frame.
130385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    }
13047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps from interceptor's holder to lookup's holder
13057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // haven't changed.  And load lookup's holder into |holder| register.
13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (*interceptor_holder != lookup->holder()) {
13077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      holder_reg = CheckPrototypes(interceptor_holder,
13087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   holder_reg,
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Handle<JSObject>(lookup->holder()),
13107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch1,
13117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch2,
13123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                   scratch3,
13137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   name,
13147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   miss);
13157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
13167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == FIELD) {
13187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found FIELD property in prototype chain of interceptor's holder.
13197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Retrieve a field from field's holder.
13207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      GenerateFastPropertyLoad(masm(), r0, holder_reg,
13213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Handle<JSObject>(lookup->holder()),
13223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               lookup->GetFieldIndex());
13237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ Ret();
13247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
13257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found CALLBACKS property in prototype chain of interceptor's
13267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // holder.
13277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(lookup->type() == CALLBACKS);
13283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<AccessorInfo> callback(
13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject()));
13307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(callback->getter() != NULL);
13317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Tail call to runtime.
13337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Important invariant in CALLBACKS case: the code above must be
13347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // structured to never clobber |receiver| register.
13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Move(scratch2, callback);
13367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // holder_reg is either receiver or scratch1.
13377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      if (!receiver.is(holder_reg)) {
13387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        ASSERT(scratch1.is(holder_reg));
13398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ Push(receiver, holder_reg);
13408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ ldr(scratch3,
13418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang               FieldMemOperand(scratch2, AccessorInfo::kDataOffset));
13428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ Push(scratch3, scratch2, name_reg);
13437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      } else {
13447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        __ push(receiver);
13458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ ldr(scratch3,
13468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang               FieldMemOperand(scratch2, AccessorInfo::kDataOffset));
13478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ Push(holder_reg, scratch3, scratch2, name_reg);
13487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      }
13497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ExternalReference ref =
135144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
135244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            masm()->isolate());
13537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ TailCallExternalReference(ref, 5, 1);
13547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
13557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {  // !compile_followup_inline
13567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Call the runtime system to load the interceptor.
13577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps haven't changed.
13587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
13593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          scratch1, scratch2, scratch3,
13603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          name, miss);
13617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    PushInterceptorArguments(masm(), receiver, holder_reg,
13627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                             name_reg, interceptor_holder);
13637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
136444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExternalReference ref =
136544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
136644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          masm()->isolate());
13677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ TailCallExternalReference(ref, 5, 1);
13687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
13739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (kind_ == Code::KEYED_CALL_IC) {
13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(r2, Operand(name));
13759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ b(ne, miss);
13769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
13779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
13789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
13799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
138359151504615d929945dc59db37bf1166937748c6Steve Block                                                   Label* miss) {
138459151504615d929945dc59db37bf1166937748c6Steve Block  ASSERT(holder->IsGlobalObject());
138559151504615d929945dc59db37bf1166937748c6Steve Block
138659151504615d929945dc59db37bf1166937748c6Steve Block  // Get the number of arguments.
138759151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
138859151504615d929945dc59db37bf1166937748c6Steve Block
138959151504615d929945dc59db37bf1166937748c6Steve Block  // Get the receiver from the stack.
139059151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
139159151504615d929945dc59db37bf1166937748c6Steve Block
139259151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the maps haven't changed.
13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(r0, miss);
139459151504615d929945dc59db37bf1166937748c6Steve Block  CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss);
139559151504615d929945dc59db37bf1166937748c6Steve Block}
139659151504615d929945dc59db37bf1166937748c6Steve Block
139759151504615d929945dc59db37bf1166937748c6Steve Block
13983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell(
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* miss) {
140259151504615d929945dc59db37bf1166937748c6Steve Block  // Get the value from the cell.
14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r3, Operand(cell));
140459151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
140559151504615d929945dc59db37bf1166937748c6Steve Block
140659151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the cell contains the same function.
14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (heap()->InNewSpace(*function)) {
140859151504615d929945dc59db37bf1166937748c6Steve Block    // We can't embed a pointer to a function in new space so we have
140959151504615d929945dc59db37bf1166937748c6Steve Block    // to verify that the shared function info is unchanged. This has
141059151504615d929945dc59db37bf1166937748c6Steve Block    // the nice side effect that multiple closures based on the same
141159151504615d929945dc59db37bf1166937748c6Steve Block    // function can all use this call IC. Before we load through the
141259151504615d929945dc59db37bf1166937748c6Steve Block    // function, we have to verify that it still is a function.
14133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r1, miss);
141459151504615d929945dc59db37bf1166937748c6Steve Block    __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
141559151504615d929945dc59db37bf1166937748c6Steve Block    __ b(ne, miss);
141659151504615d929945dc59db37bf1166937748c6Steve Block
141759151504615d929945dc59db37bf1166937748c6Steve Block    // Check the shared function info. Make sure it hasn't changed.
141859151504615d929945dc59db37bf1166937748c6Steve Block    __ Move(r3, Handle<SharedFunctionInfo>(function->shared()));
141959151504615d929945dc59db37bf1166937748c6Steve Block    __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
142059151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(r4, r3);
142159151504615d929945dc59db37bf1166937748c6Steve Block  } else {
14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(r1, Operand(function));
142359151504615d929945dc59db37bf1166937748c6Steve Block  }
14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(ne, miss);
142559151504615d929945dc59db37bf1166937748c6Steve Block}
142659151504615d929945dc59db37bf1166937748c6Steve Block
142759151504615d929945dc59db37bf1166937748c6Steve Block
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() {
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code =
1430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                               kind_,
14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               extra_state_);
14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(code, RelocInfo::CODE_TARGET);
14347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
14357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
14395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                int index,
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r2    : name
1443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- lr    : return address
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
14489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver of the function from the stack into r0.
1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
14543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r0, &miss);
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do the right check and compute the holder register.
14573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss);
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall(
14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
14753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
14776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
14786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r2    : name
14796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- lr    : return address
14808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
14818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- ...
14828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[argc * 4]           : receiver
14836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
148559151504615d929945dc59db37bf1166937748c6Steve Block  // If object is not an array, bail out to regular call.
14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
14899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
14909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
14918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register receiver = r1;
14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack
14936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
14948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
14971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(receiver, &miss);
14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the maps haven't changed.
15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, r3, r0, r4,
15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, &miss);
15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (argc == 0) {
15048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    // Nothing to do, just return the length.
15058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
15068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Drop(argc + 1);
15078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Ret();
15088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  } else {
15098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    Label call_builtin;
15108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (argc == 1) {  // Otherwise fall through to call the builtin.
15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label attempt_to_grow_elements;
15138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register elements = r6;
15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register end_elements = r5;
15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements array of the object.
15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
15185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check that the elements are in fast mode and writable.
15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckMap(elements,
15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  r0,
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Heap::kFixedArrayMapRootIndex,
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  &call_builtin,
15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  DONT_DO_SMI_CHECK);
15255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
15265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
15278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Get the array's length into r0 and calculate new length.
15288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
15298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      STATIC_ASSERT(kSmiTagSize == 1);
15308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      STATIC_ASSERT(kSmiTag == 0);
15318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(r0, r0, Operand(Smi::FromInt(argc)));
15328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements' length.
15348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
15358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Check if we could survive without allocation.
15378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ cmp(r0, r4);
15388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ b(gt, &attempt_to_grow_elements);
15398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if value is a smi.
15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label with_write_barrier;
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfNotSmi(r4, &with_write_barrier);
15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Save new length.
15468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
15478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
15498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // We may need a register containing the address end_elements below,
15508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // so write back the value in end_elements.
15518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(end_elements, elements,
15528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang             Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
15538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      const int kEndElementsOffset =
15548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang          FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
15558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
15568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Check for a smi.
15588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Drop(argc + 1);
15598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Ret();
15608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ bind(&with_write_barrier);
15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset));
15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_smi_only_arrays  && !FLAG_trace_elements_transitions) {
15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label fast_object, not_fast_object;
15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(r3, r7, &not_fast_object);
15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&fast_object);
15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // In case of fast smi-only, convert to fast object, otherwise bail out.
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&not_fast_object);
15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastSmiOnlyElements(r3, r7, &call_builtin);
15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // edx: receiver
15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // r3: map
15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               FAST_ELEMENTS,
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               r3,
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               r7,
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               &call_builtin);
15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(r2, receiver);
15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm());
15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&fast_object);
15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(r3, r3, &call_builtin);
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Save new length.
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // We may need a register containing the address end_elements below,
15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // so write back the value in end_elements.
15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(end_elements, elements,
15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWrite(elements,
15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     end_elements,
15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     r4,
15993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     kLRHasNotBeenSaved,
16003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     kDontSaveFPRegs,
16013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     EMIT_REMEMBERED_SET,
16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     OMIT_SMI_CHECK);
16038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Drop(argc + 1);
16048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Ret();
16058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ bind(&attempt_to_grow_elements);
16078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // r0: array's length + 1.
16088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // r4: elements' length.
16098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      if (!FLAG_inline_new) {
16118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ b(&call_builtin);
16128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      }
16138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r2, MemOperand(sp, (argc - 1) * kPointerSize));
16153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Growing elements that are SMI-only requires special handling in case
16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the new element is non-Smi. For now, delegate to the builtin.
16173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label no_fast_elements_check;
16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfSmi(r2, &no_fast_elements_check);
16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r7, FieldMemOperand(receiver, HeapObject::kMapOffset));
16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckFastObjectElements(r7, r7, &call_builtin);
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&no_fast_elements_check);
16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
162344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate* isolate = masm()->isolate();
16248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      ExternalReference new_space_allocation_top =
162544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_top_address(isolate);
16268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      ExternalReference new_space_allocation_limit =
162744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_limit_address(isolate);
16288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      const int kAllocationDelta = 4;
16308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Load top and check if it is the end of elements.
16318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(end_elements, elements,
16328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang             Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
16338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(end_elements, end_elements, Operand(kEndElementsOffset));
16348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ mov(r7, Operand(new_space_allocation_top));
16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r3, MemOperand(r7));
16363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(end_elements, r3);
16378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ b(ne, &call_builtin);
16388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ mov(r9, Operand(new_space_allocation_limit));
16408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ ldr(r9, MemOperand(r9));
16413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(r3, r3, Operand(kAllocationDelta * kPointerSize));
16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(r3, r9);
16438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ b(hi, &call_builtin);
16448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // We fit and could grow elements.
16468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Update new_space_allocation_top.
16473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r3, MemOperand(r7));
16488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Push the argument.
16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r2, MemOperand(end_elements));
16508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Fill the rest with holes.
16513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
16528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      for (int i = 1; i < kAllocationDelta; i++) {
16533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ str(r3, MemOperand(end_elements, i * kPointerSize));
16548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      }
16558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Update elements' and array's sizes.
16578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
16588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta)));
16598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
16608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Elements are in new space, so write barrier is not required.
16628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Drop(argc + 1);
16638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Ret();
16648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    }
16658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ bind(&call_builtin);
166644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
166744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   masm()->isolate()),
16688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 argc + 1,
16698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 1);
16708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
16716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Handle call cache miss.
16736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
16743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
16756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
167725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
16786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
16796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16813ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall(
16823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
16833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
16843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
16853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
16863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1688402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r2    : name
1689402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- lr    : return address
16908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
16918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- ...
16928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[argc * 4]           : receiver
1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
16946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
169559151504615d929945dc59db37bf1166937748c6Steve Block  // If object is not an array, bail out to regular call.
16963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
16976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label miss, return_undefined, call_builtin;
16998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register receiver = r1;
17008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register elements = r3;
17019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
17029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack
1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
17058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
17071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(receiver, &miss);
17086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the maps haven't changed.
17103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, elements,
17113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  r4, r0, name, &miss);
17128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Get the elements array of the object.
17148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
17156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check that the elements are in fast mode and writable.
1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(elements,
1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              r0,
1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              Heap::kFixedArrayMapRootIndex,
1720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              &call_builtin,
1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              DONT_DO_SMI_CHECK);
17228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Get the array's length into r4 and calculate new length.
17248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
17258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC);
17268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(lt, &return_undefined);
17278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Get the last element.
17298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
17308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(kSmiTagSize == 1);
17318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(kSmiTag == 0);
17328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We can't address the last element in one operation. Compute the more
17338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // expensive shift first, and use an offset later on.
17348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ add(elements, elements, Operand(r4, LSL, kPointerSizeLog2 - kSmiTagSize));
17358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r0, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag));
17368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(r0, r6);
17378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(eq, &call_builtin);
17388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Set the array's length.
17408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
17418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Fill with the hole.
17438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(r6, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag));
17448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(argc + 1);
17458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
17468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&return_undefined);
17488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
17498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(argc + 1);
17508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
17518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&call_builtin);
175344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop,
175444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 masm()->isolate()),
17556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               argc + 1,
17566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               1);
17576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Handle call cache miss.
17596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
17603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
17616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
176325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
17646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
17683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
17693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
177380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ----------- S t a t e -------------
177480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- r2                     : function name
177580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- lr                     : return address
177680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
177780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- ...
177880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- sp[argc * 4]           : receiver
177980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // -----------------------------------
178080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
178180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If object is not a string, bail out to regular call.
17823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
178380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
178480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const int argc = arguments().immediate();
178580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label miss;
1786b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
178780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label index_out_of_range;
1788b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
1789b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
17913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1793b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1794b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1795b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
179680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
179780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the maps starting from the prototype haven't changed.
179880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateDirectLoadGlobalFunctionPrototype(masm(),
179980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                            Context::STRING_FUNCTION_INDEX,
18000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            r0,
18010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
18023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
18043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  r0, holder, r1, r3, r4, name, &miss);
180580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
180680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register receiver = r1;
180780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register index = r4;
180880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register result = r0;
180980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
181080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (argc > 0) {
181180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
181280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
181380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
181480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
181580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
18163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharCodeAtGenerator generator(receiver,
18173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index,
18183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      result,
18193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a string.
18203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a number.
18213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index_out_of_range_label,
18223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      STRING_INDEX_IS_NUMBER);
18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
182480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Drop(argc + 1);
182580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Ret();
182680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
182980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1830b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1831b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
1832b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ LoadRoot(r0, Heap::kNanValueRootIndex);
1833b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ Drop(argc + 1);
1834b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ Ret();
1835b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
183680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
183780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&miss);
1838b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in r2.
18393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(r2, name);
1840b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
18413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
184280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
184380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Return the generated code.
184480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return GetCode(function);
18457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
18467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall(
18493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
18503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
18513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
18523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
18533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
185480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ----------- S t a t e -------------
185580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- r2                     : function name
185680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- lr                     : return address
185780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
185880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- ...
185980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- sp[argc * 4]           : receiver
186080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // -----------------------------------
186180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
186280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If object is not a string, bail out to regular call.
18633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
186480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
186580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const int argc = arguments().immediate();
186680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label miss;
1867b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
186880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label index_out_of_range;
1869b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
1870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
18713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1873b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1874b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1875b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
187680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
187780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the maps starting from the prototype haven't changed.
187880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateDirectLoadGlobalFunctionPrototype(masm(),
187980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                            Context::STRING_FUNCTION_INDEX,
18800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            r0,
18810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
18823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
18833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
18843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  r0, holder, r1, r3, r4, name, &miss);
188580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
188680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register receiver = r0;
188780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register index = r4;
18883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = r3;
188980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register result = r0;
189080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
189180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (argc > 0) {
189280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
189380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
189480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
189580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
189680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
18973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharAtGenerator generator(receiver,
18983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index,
18993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  scratch,
19003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  result,
19013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a string.
19023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a number.
19033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index_out_of_range_label,
19043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  STRING_INDEX_IS_NUMBER);
19053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
190680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Drop(argc + 1);
190780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Ret();
190880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
19103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
191180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1912b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1913b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
1914b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ LoadRoot(r0, Heap::kEmptyStringRootIndex);
1915b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ Drop(argc + 1);
1916b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ Ret();
1917b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
191880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
191980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&miss);
1920b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in r2.
19213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(r2, name);
1922b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
19233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
192480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
192580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Return the generated code.
192680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return GetCode(function);
19277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
19287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
19297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
19313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
19323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
19333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
19343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
19353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
193659151504615d929945dc59db37bf1166937748c6Steve Block  // ----------- S t a t e -------------
193759151504615d929945dc59db37bf1166937748c6Steve Block  //  -- r2                     : function name
193859151504615d929945dc59db37bf1166937748c6Steve Block  //  -- lr                     : return address
193959151504615d929945dc59db37bf1166937748c6Steve Block  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
194059151504615d929945dc59db37bf1166937748c6Steve Block  //  -- ...
194159151504615d929945dc59db37bf1166937748c6Steve Block  //  -- sp[argc * 4]           : receiver
194259151504615d929945dc59db37bf1166937748c6Steve Block  // -----------------------------------
194359151504615d929945dc59db37bf1166937748c6Steve Block
194459151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
194559151504615d929945dc59db37bf1166937748c6Steve Block
194659151504615d929945dc59db37bf1166937748c6Steve Block  // If the object is not a JSObject or we got an unexpected number of
194759151504615d929945dc59db37bf1166937748c6Steve Block  // arguments, bail out to the regular call.
19483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
194959151504615d929945dc59db37bf1166937748c6Steve Block
195059151504615d929945dc59db37bf1166937748c6Steve Block  Label miss;
195159151504615d929945dc59db37bf1166937748c6Steve Block  GenerateNameCheck(name, &miss);
195259151504615d929945dc59db37bf1166937748c6Steve Block
19533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
195459151504615d929945dc59db37bf1166937748c6Steve Block    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
195559151504615d929945dc59db37bf1166937748c6Steve Block
195659151504615d929945dc59db37bf1166937748c6Steve Block    STATIC_ASSERT(kSmiTag == 0);
19573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r1, &miss);
195859151504615d929945dc59db37bf1166937748c6Steve Block
19593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4,
19603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
196159151504615d929945dc59db37bf1166937748c6Steve Block  } else {
19623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
19633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
19643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
196559151504615d929945dc59db37bf1166937748c6Steve Block    GenerateLoadFunctionFromCell(cell, function, &miss);
196659151504615d929945dc59db37bf1166937748c6Steve Block  }
196759151504615d929945dc59db37bf1166937748c6Steve Block
196859151504615d929945dc59db37bf1166937748c6Steve Block  // Load the char code argument.
196959151504615d929945dc59db37bf1166937748c6Steve Block  Register code = r1;
197059151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(code, MemOperand(sp, 0 * kPointerSize));
197159151504615d929945dc59db37bf1166937748c6Steve Block
197259151504615d929945dc59db37bf1166937748c6Steve Block  // Check the code is a smi.
197359151504615d929945dc59db37bf1166937748c6Steve Block  Label slow;
197459151504615d929945dc59db37bf1166937748c6Steve Block  STATIC_ASSERT(kSmiTag == 0);
19753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(code, &slow);
197659151504615d929945dc59db37bf1166937748c6Steve Block
197759151504615d929945dc59db37bf1166937748c6Steve Block  // Convert the smi code to uint16.
197859151504615d929945dc59db37bf1166937748c6Steve Block  __ and_(code, code, Operand(Smi::FromInt(0xffff)));
197959151504615d929945dc59db37bf1166937748c6Steve Block
19803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharFromCodeGenerator generator(code, r0);
19813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
198259151504615d929945dc59db37bf1166937748c6Steve Block  __ Drop(argc + 1);
198359151504615d929945dc59db37bf1166937748c6Steve Block  __ Ret();
198459151504615d929945dc59db37bf1166937748c6Steve Block
1985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
19863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
198759151504615d929945dc59db37bf1166937748c6Steve Block
198859151504615d929945dc59db37bf1166937748c6Steve Block  // Tail call the full function. We do not have to patch the receiver
198959151504615d929945dc59db37bf1166937748c6Steve Block  // because the function makes no use of it.
199059151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&slow);
19913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(
19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function,  arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
199359151504615d929945dc59db37bf1166937748c6Steve Block
199459151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&miss);
199559151504615d929945dc59db37bf1166937748c6Steve Block  // r2: function name.
19963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
199759151504615d929945dc59db37bf1166937748c6Steve Block
199859151504615d929945dc59db37bf1166937748c6Steve Block  // Return the generated code.
19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
200059151504615d929945dc59db37bf1166937748c6Steve Block}
200159151504615d929945dc59db37bf1166937748c6Steve Block
200259151504615d929945dc59db37bf1166937748c6Steve Block
20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall(
20043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
20053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
20073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
20098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // ----------- S t a t e -------------
20108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- r2                     : function name
20118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- lr                     : return address
20128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
20138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- ...
20148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[argc * 4]           : receiver
20158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // -----------------------------------
20168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!CpuFeatures::IsSupported(VFP3)) {
20183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
201944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
202044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
20218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CpuFeatures::Scope scope_vfp3(VFP3);
20228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int argc = arguments().immediate();
20238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If the object is not a JSObject or we got an unexpected number of
20248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // arguments, bail out to the regular call.
20253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
20268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label miss, slow;
20288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  GenerateNameCheck(name, &miss);
20298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
20318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
20328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    STATIC_ASSERT(kSmiTag == 0);
20331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ JumpIfSmi(r1, &miss);
20343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4,
20353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
20368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  } else {
20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
20383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
20393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
20408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    GenerateLoadFunctionFromCell(cell, function, &miss);
20418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
20428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the (only) argument into r0.
20448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r0, MemOperand(sp, 0 * kPointerSize));
20458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If the argument is a smi, just return.
20478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(kSmiTag == 0);
20488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ tst(r0, Operand(kSmiTagMask));
20498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(argc + 1, eq);
20508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret(eq);
20518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
20538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label wont_fit_smi, no_vfp_exception, restore_fpscr_and_return;
20558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If vfp3 is enabled, we use the fpu rounding with the RM (round towards
20578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // minus infinity) mode.
20588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the HeapNumber value.
20608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We will need access to the value in the core registers, so we load it
20618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // with ldrd and move it to the fpu. It also spares a sub instruction for
20628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // updating the HeapNumber value address, as vldr expects a multiple
20638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // of 4 offset.
20648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ldrd(r4, r5, FieldMemOperand(r0, HeapNumber::kValueOffset));
20658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmov(d1, r4, r5);
20668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Backup FPSCR.
20688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmrs(r3);
20698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Set custom FPCSR:
20708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  - Set rounding mode to "Round towards Minus Infinity"
20713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    (i.e. bits [23:22] = 0b10).
20728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  - Clear vfp cumulative exception flags (bits [3:0]).
20738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  - Make sure Flush-to-zero mode control bit is unset (bit 22).
20748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bic(r9, r3,
20758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask));
20761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ orr(r9, r9, Operand(kRoundToMinusInf));
20778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmsr(r9);
20788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Convert the argument to an integer.
20801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
20818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Use vcvt latency to start checking for special cases.
20838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Get the argument exponent and clear the sign bit.
20848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bic(r6, r5, Operand(HeapNumber::kSignMask));
20858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(r6, Operand(r6, LSR, HeapNumber::kMantissaBitsInTopWord));
20868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Retrieve FPSCR and check for vfp exceptions.
20888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmrs(r9);
20898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ tst(r9, Operand(kVFPExceptionMask));
20908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&no_vfp_exception, eq);
20918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check for NaN, Infinity, and -Infinity.
20938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // They are invariant through a Math.Floor call, so just
20948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // return the original argument.
20958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ sub(r7, r6, Operand(HeapNumber::kExponentMask
20968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        >> HeapNumber::kMantissaBitsInTopWord), SetCC);
20978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&restore_fpscr_and_return, eq);
20988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We had an overflow or underflow in the conversion. Check if we
20998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // have a big exponent.
21008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(r7, Operand(HeapNumber::kMantissaBits));
21018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If greater or equal, the argument is already round and in r0.
21028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&restore_fpscr_and_return, ge);
2103b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ b(&wont_fit_smi);
21048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&no_vfp_exception);
21068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Move the result back to general purpose register r0.
21078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmov(r0, s0);
21088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check if the result fits into a smi.
21098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ add(r1, r0, Operand(0x40000000), SetCC);
21108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&wont_fit_smi, mi);
21118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Tag the result.
21128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(kSmiTag == 0);
21138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
21148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check for -0.
2116b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(r0, Operand(0, RelocInfo::NONE));
21178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&restore_fpscr_and_return, ne);
21188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // r5 already holds the HeapNumber exponent.
21198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ tst(r5, Operand(HeapNumber::kSignMask));
21208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If our HeapNumber is negative it was -0, so load its address and return.
21218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Else r0 is loaded with 0, so we can also just return.
21228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r0, MemOperand(sp, 0 * kPointerSize), ne);
21238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&restore_fpscr_and_return);
21258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Restore FPSCR and return.
21268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmsr(r3);
21278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(argc + 1);
21288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
21298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&wont_fit_smi);
21318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Restore FPCSR and fall to slow case.
21328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmsr(r3);
21338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2134b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&slow);
21358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Tail call the full function. We do not have to patch the receiver
21368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // because the function makes no use of it.
21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(
21383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
21398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&miss);
21418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // r2: function name.
21423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
21438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Return the generated code.
21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
21460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
21470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
21480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
21493ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall(
21503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
21513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
21523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
21533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
21543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2155f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // ----------- S t a t e -------------
2156f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- r2                     : function name
2157f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- lr                     : return address
2158f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
2159f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- ...
2160f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- sp[argc * 4]           : receiver
2161f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // -----------------------------------
2162f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2163f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const int argc = arguments().immediate();
2164f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the object is not a JSObject or we got an unexpected number of
2165f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // arguments, bail out to the regular call.
21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2167f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2168f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label miss;
2169f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  GenerateNameCheck(name, &miss);
21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
2171f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
2172f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
21733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r1, &miss);
21743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4,
21753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
2176f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  } else {
21773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
21783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
21793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
2180f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    GenerateLoadFunctionFromCell(cell, function, &miss);
2181f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
2182f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2183f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Load the (only) argument into r0.
2184f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ldr(r0, MemOperand(sp, 0 * kPointerSize));
2185f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2186f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check if the argument is a smi.
2187f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label not_smi;
2188f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
21891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfNotSmi(r0, &not_smi);
2190f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2191f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Do bitwise not or do nothing depending on the sign of the
2192f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // argument.
2193f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ eor(r1, r0, Operand(r0, ASR, kBitsPerInt - 1));
2194f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2195f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Add 1 or do nothing depending on the sign of the argument.
2196f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ sub(r0, r1, Operand(r0, ASR, kBitsPerInt - 1), SetCC);
2197f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2198f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the result is still negative, go to the slow case.
2199f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // This only happens for the most negative smi.
2200f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label slow;
2201f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ b(mi, &slow);
2202f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2203f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Smi case done.
2204f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Drop(argc + 1);
2205f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Ret();
2206f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2207f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check if the argument is a heap number and load its exponent and
2208f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // sign.
2209f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&not_smi);
2210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
2211f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ldr(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset));
2212f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2213f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check the sign of the argument. If the argument is positive,
2214f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // just return it.
2215f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label negative_sign;
2216f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ tst(r1, Operand(HeapNumber::kSignMask));
2217f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ b(ne, &negative_sign);
2218f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Drop(argc + 1);
2219f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Ret();
2220f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2221f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the argument is negative, clear the sign, and return a new
2222f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // number.
2223f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&negative_sign);
2224f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ eor(r1, r1, Operand(HeapNumber::kSignMask));
2225f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
2226f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
2227f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ AllocateHeapNumber(r0, r4, r5, r6, &slow);
2228f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset));
2229f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
2230f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Drop(argc + 1);
2231f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Ret();
2232f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2233f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Tail call the full function. We do not have to patch the receiver
2234f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // because the function makes no use of it.
2235f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&slow);
22363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(
22373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
2238f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2239f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&miss);
2240f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // r2: function name.
22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2242f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2243f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Return the generated code.
22443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
2245f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
2246f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2247f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall(
224944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    const CallOptimization& optimization,
22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
22533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
22543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
225544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
225644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
225744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(optimization.is_simple_api_call());
225844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Bail out if object is a global object as we don't want to
225944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // repatch it to global receiver.
22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (object->IsGlobalObject()) return Handle<Code>::null();
22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!cell.is_null()) return Handle<Code>::null();
22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject()) return Handle<Code>::null();
226344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int depth = optimization.GetPrototypeDepthOfExpectedType(
22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<JSObject>::cast(object), holder);
22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (depth == kInvalidProtoDepth) return Handle<Code>::null();
226644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
226744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss, miss_before_stack_reserved;
226844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss_before_stack_reserved);
226944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
227044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the receiver from the stack.
227144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int argc = arguments().immediate();
227244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
227344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
227444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the receiver isn't a smi.
22753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r1, &miss_before_stack_reserved);
227644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
227744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const(), 1, r0, r3);
227844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3);
227944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
228044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ReserveSpaceForFastApiCall(masm(), r0);
228144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
228244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the maps haven't changed and find a Holder as a side effect.
22833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, name,
228444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                  depth, &miss);
228544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
22863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateFastApiDirectCall(masm(), optimization, argc);
228744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
228844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss);
228944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  FreeSpaceForFastApiCall(masm());
229044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
229144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss_before_stack_reserved);
22923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
229344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
229444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Return the generated code.
229544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return GetCode(function);
229644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
229744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
229844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> function,
23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
23035913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   CheckType check) {
23046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
23056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r2    : name
23066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- lr    : return address
23076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
230844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder,
23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Handle<JSGlobalPropertyCell>::null(),
23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          function, name);
23123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
23133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
23146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
23156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
231644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss;
231744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss);
23189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
23196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack
23206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
23216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
23226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
23236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check != NUMBER_CHECK) {
23253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r1, &miss);
2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that it's okay not to patch the on stack receiver
2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // unless we're doing a receiver map check.
2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (check) {
2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RECEIVER_MAP_CHECK:
233344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ IncrementCounter(masm()->isolate()->counters()->call_const(),
233444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          1, r0, r3);
23356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the maps haven't changed.
23373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4,
23383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      name, &miss);
2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Patch the receiver on the stack with the global proxy if
2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // necessary.
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsGlobalObject()) {
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ str(r3, MemOperand(sp, argc * kPointerSize));
2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case STRING_CHECK:
23493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a two-byte string or a symbol.
2351402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
23523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        __ b(ge, &miss);
2353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
23547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
23550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::STRING_FUNCTION_INDEX, r0, &miss);
23563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
23573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
23583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            r0, holder, r3, r1, r4, 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()) {
2368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
2369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a smi or a heap number.
23703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        __ JumpIfSmi(r1, &fast);
2371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE);
2372e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ b(ne, &miss);
2373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
2374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
23757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
23760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss);
23773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
23783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
23793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            r0, holder, r3, r1, r4, 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()) {
2389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
2390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a boolean.
2391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ LoadRoot(ip, Heap::kTrueValueRootIndex);
2392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ cmp(r1, ip);
2393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ b(eq, &fast);
2394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ LoadRoot(ip, Heap::kFalseValueRootIndex);
2395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ cmp(r1, ip);
2396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ b(ne, &miss);
2397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
2398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
23997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
24000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss);
24013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
24023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
24033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            r0, holder, r3, r1, r4, name, &miss);
24043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
24053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
24063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // requires boxing.
24073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&miss);
2408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
24153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(
24163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind);
2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
24203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
242325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24273ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
24293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r2    : name
2432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- lr    : return address
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
24346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
24359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
24369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
24374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Get the number of arguments.
24384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  const int argc = arguments().immediate();
24393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
24404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  LookupPostInterceptor(holder, name, &lookup);
24414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
24426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack.
24436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
2444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
24453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_);
24463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0,
24473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   &miss);
2448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Move returned value, the function to call, to r1.
2450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(r1, r0);
24514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Restore receiver.
24526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
24534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
24543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
24583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24653ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal(
24663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
24673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
24693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r2    : name
2473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- lr    : return address
2474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
247544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
24763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
24773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
24783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
247959151504615d929945dc59db37bf1166937748c6Steve Block  }
248059151504615d929945dc59db37bf1166937748c6Steve Block
2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
24829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
24839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments.
2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
248659151504615d929945dc59db37bf1166937748c6Steve Block  GenerateGlobalReceiverCheck(object, holder, name, &miss);
248759151504615d929945dc59db37bf1166937748c6Steve Block  GenerateLoadFunctionFromCell(cell, function, &miss);
2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy if
2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary.
2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r3, MemOperand(sp, argc * kPointerSize));
2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the context (function already in r1).
2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the cached code (tail call).
250044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
250144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline(), 1, r3, r4);
2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(function->shared()->formal_parameter_count());
25033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
25063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We call indirectly through the code field in the function to
25073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // allow recompilation to take effect without changing any of the
25083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // call sites.
25093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION,
25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                NullCallWrapper(), call_kind);
2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
251544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3);
25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25233ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
25245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  int index,
25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<Map> transition,
25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<String> name) {
2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
2529402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r1    : receiver
2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, r1, r2, r3, &miss);
2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
253744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
25413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25453ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback(
25463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
25473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback,
25483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
2551402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r1    : receiver
2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
25583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(r1, r3, Handle<Map>(object->map()), &miss,
25593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
2563402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ CheckAccessGlobalProxy(r1, r3, &miss);
2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2570402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(r1);  // receiver
25713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ip, Operand(callback));  // callback info
25726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(ip, r2, r0);
2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_callback_property =
257644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreCallbackProperty),
257744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        masm()->isolate());
25786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(store_callback_property, 4, 1);
2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
258244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor(
25913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
25923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
2595402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r1    : receiver
2596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
26023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(r1, r3, Handle<Map>(receiver->map()), &miss,
26033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (receiver->IsJSGlobalProxy()) {
2607402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ CheckAccessGlobalProxy(r1, r3, &miss);
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2610402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Stub is never generated for non-global objects that require access
2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(r1, r2, r0);  // Receiver, name, value.
2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2616e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ mov(r0, Operand(Smi::FromInt(strict_mode_)));
2617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(r0);  // strict mode
2618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_ic_property =
262144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty),
262244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        masm()->isolate());
2623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ TailCallExternalReference(store_ic_property, 4, 1);
2624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
262744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26353ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal(
26363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> object,
26373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
26383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
2641402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r1    : receiver
2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
2648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r3, Operand(Handle<Map>(object->map())));
2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the value in the cell is not the hole. If it is, this
26531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // cell could have been deleted and reintroducing the global needs
26541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // to update the property details in the property dictionary of the
26551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // global object. We bail out to the runtime system to do that.
26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r4, Operand(cell));
26571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
26581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(r6, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset));
26591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ cmp(r5, r6);
26601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ b(eq, &miss);
26611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Store the value in the cell.
26631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ str(r0, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset));
26643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Cells are always rescanned, so no write barrier here.
2665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
266644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
266744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline(), 1, r4, r3);
2668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
2669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
267244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline_miss(), 1, r4, r3);
267344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
2674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26813ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
26823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> object,
26833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> last) {
26846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
26866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- lr    : return address
26876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
26886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
26896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that receiver is not a smi.
26913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r0, &miss);
26926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the maps of the full prototype chain.
26943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss);
26956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If the last object in the prototype chain is a global object,
26976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // check that the global property cell is empty.
26986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (last->IsGlobalObject()) {
26993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateCheckPropertyCell(
27003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm(), Handle<GlobalObject>::cast(last), name, r1, &miss);
27016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
27026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return undefined if maps of the full prototype chain are still the
27046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // same and no global property with this name contains a value.
27056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
27066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Ret();
27076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
27096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
27106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NONEXISTENT, factory()->empty_string());
27136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
27146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27163ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
27173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
27185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                int index,
27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
2720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(object, holder, r0, r3, r1, r4, index, name, &miss);
2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27363ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback(
27373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
27383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
27393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4, callback, name,
27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       &miss);
2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> value,
27603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name) {
2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadConstant(object, holder, r0, r3, r1, r4, value, name, &miss);
2769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27773ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object,
27783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
27793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
27884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  LookupPostInterceptor(holder, name, &lookup);
27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(object, holder, &lookup, r0, r2, r3, r1, r4, name,
2790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &miss);
2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal(
28003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
28013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
28023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
28033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_dont_delete) {
2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
28133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(r0, &miss);
28143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss);
2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value from the cell.
28173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r3, Operand(cell));
28186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for deleted property if property can actually be deleted.
2821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!is_dont_delete) {
2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
28236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ cmp(r4, ip);
2824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &miss);
2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r0, r4);
282844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
282944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3);
2830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
2831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
283344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub_miss(), 1, r1, r3);
2834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28413ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
28423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> receiver,
28433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> holder,
28445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                     int index) {
2845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
28476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
284825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
28533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
2854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss);
2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28643ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback(
28653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
28716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
287225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
28773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
2878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, r4, callback, name,
28813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       &miss);
2882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28893ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant(
28903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
28913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> value) {
2894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
28966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
289725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
29023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
2903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss);
2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
2911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29143ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
29153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
29163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
29173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
29206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
292125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
29263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
2927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
29304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  LookupPostInterceptor(holder, name, &lookup);
29313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(receiver, holder, &lookup, r1, r0, r2, r3, r4, name,
2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &miss);
2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29403ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
29413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
29446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
294525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
29503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateLoadArrayLength(masm(), r1, r2, &miss);
2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29613ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
29623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
29656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
296625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
296944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
297044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
297144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_string_length(), 1, r2, r3);
2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
29743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateLoadStringLength(masm(), r1, r2, r3, &miss, true);
2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
297944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_string_length(), 1, r2, r3);
2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29873ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
29883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
29916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
299225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
29948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label miss;
29958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
299644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
299744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3);
29988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
29998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check the name hasn't changed.
30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
30018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(ne, &miss);
30028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
30038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss);
30048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&miss);
300544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3);
3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement(
30133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
3014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
3015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- lr    : return address
3016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r0    : key
3017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r1    : receiver
3018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
3019589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
30203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode();
30213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK);
3023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
3026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
30283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
3029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30323ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic(
30333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
30343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_ics) {
3035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- lr    : return address
3037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r0    : key
3038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r1    : receiver
3039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
3041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(r1, &miss);
3042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int receiver_count = receiver_maps->length();
3044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
3045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int current = 0; current < receiver_count; ++current) {
30463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ip, Operand(receiver_maps->at(current)));
3047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cmp(r2, ip);
30483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Jump(handler_ics->at(current), RelocInfo::CODE_TARGET, eq);
3049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
3052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss();
3053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
3054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Return the generated code.
30563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
3057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30603ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
30615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                       int index,
30623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<Map> transition,
30633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<String> name) {
3064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
3065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
3066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r1    : name
3067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r2    : receiver
3068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
3069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
3070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
3071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
307244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
307344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_store_field(), 1, r3, r4);
3074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
30763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r1, Operand(name));
3077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
3078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r3 is used as scratch register. r1 and r2 keep their values if a jump to
3080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the miss label is generated.
30813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, r2, r1, r3, &miss);
3082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
3083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
308444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4);
308544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
3086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
3087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
30893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
3090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30933ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement(
30943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
3095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
3096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r0    : value
3097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r1    : key
3098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r2    : receiver
3099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- lr    : return address
3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r3    : scratch
3101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
3102589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
3103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
31043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub =
31053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode();
31063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(r2, r3, receiver_map, stub, DO_SMI_CHECK);
3108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
3111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
31133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
3114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31173ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
31183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
31193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_stubs,
31203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* transitioned_maps) {
3121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r0    : value
3123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r1    : key
3124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r2    : receiver
3125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- lr    : return address
3126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r3    : scratch
3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
3129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(r2, &miss);
3130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int receiver_count = receiver_maps->length();
3132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
31333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < receiver_count; ++i) {
31343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ip, Operand(receiver_maps->at(i)));
3135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cmp(r3, ip);
31363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (transitioned_maps->at(i).is_null()) {
31373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq);
31383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
31393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label next_map;
31403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ b(ne, &next_map);
31413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r3, Operand(transitioned_maps->at(i)));
31423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, al);
31433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&next_map);
31443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
3148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
3149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
3150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Return the generated code.
31523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
3153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
3154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
31563ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub(
31573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function) {
3158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
3159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : argc
3160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1    : constructor
3161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
3162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp]  : last argument
3163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
3164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_stub_call;
3165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use r7 for holding undefined which is used in several places below.
3167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
3168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
3170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check to see whether there are any break points in the function code. If
3171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // there are jump to the generic constructor stub which calls the actual
3172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code for the function thereby hitting the break points.
3173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
3174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset));
3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, r7);
3176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &generic_stub_call);
3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map and verify that it is in fact a map.
3180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
3182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
31833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r2, &generic_stub_call);
3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(r2, r3, r4, MAP_TYPE);
3185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &generic_stub_call);
3186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
3188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cannot construct functions this way.
3189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
3190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
3191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: initial map
3192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
3193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
3194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Check(ne, "Function constructed by construct stub.");
3195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Now allocate the JSObject in new space.
3198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
3199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
3200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: initial map
3201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
3202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
32033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AllocateInNewSpace(r3, r4, r5, r6, &generic_stub_call, SIZE_IN_WORDS);
3204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSObject, now initialize the fields. Map is set to initial
3206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // map and properties and elements are set to empty fixed array.
3207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
3208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
3209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: initial map
3210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: object size (in words)
3211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject (not tagged)
3212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
3213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
3214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r5, r4);
3215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
3216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
3217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
3218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
3219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
3220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
3221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the first argument. The stack contains only the
3223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // argc arguments.
3224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2));
3225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill all the in-object properties with undefined.
3227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
3228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: first argument
3229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: object size (in words)
3230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject (not tagged)
3231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r5: First in-object property of JSObject (not tagged)
3232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
3233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the initialized properties with a constant value or a passed argument
3234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // depending on the this.x = ...; assignment in the function.
32353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<SharedFunctionInfo> shared(function->shared());
3236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
3237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (shared->IsThisPropertyAssignmentArgument(i)) {
3238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Label not_passed, next;
3239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check if the argument assigned to the property is actually passed.
3240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int arg_number = shared->GetThisPropertyAssignmentArgument(i);
3241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(r0, Operand(arg_number));
3242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(le, &not_passed);
3243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Argument passed - find it on the stack.
3244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ ldr(r2, MemOperand(r1, (arg_number + 1) * -kPointerSize));
3245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
3246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(&next);
3247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&not_passed);
3248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to undefined.
3249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
3250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&next);
3251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
3252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to the constant value.
3253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
3254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ mov(r2, Operand(constant));
3255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
3256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the unused in-object property fields with undefined.
32608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(function->has_initial_map());
3261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = shared->this_property_assignments_count();
32628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang       i < function->initial_map()->inobject_properties();
3263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       i++) {
3264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
3265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
3268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject (not tagged)
3269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move argc to r1 and the JSObject to return to r0 and tag it.
3270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r1, r0);
3271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r4);
3272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ orr(r0, r0, Operand(kHeapObjectTag));
3273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: JSObject
3275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: argc
3276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack and return.
3277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2));
3278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
327944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
328044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects(), 1, r1, r2);
328144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects_stub(), 1, r1, r2);
3282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
3283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic stub in case the specialized code cannot handle the
3285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // construction.
3286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_stub_call);
328744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric();
328844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Jump(code, RelocInfo::CODE_TARGET);
3289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode();
3292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __
32963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm)
32973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
33003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
33013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ---------- S t a t e --------------
33023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- lr     : return address
33033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r0     : key
33043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r1     : receiver
3305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
33063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, miss_force_generic;
3307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register key = r0;
33093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register receiver = r1;
3310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(key, &miss_force_generic);
33123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(r2, Operand(key, ASR, kSmiTagSize));
33133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
33143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadFromNumberDictionary(&slow, r4, key, r0, r2, r3, r5);
33153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
3316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
33183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ IncrementCounter(
33193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->counters()->keyed_load_external_array_slow(),
33203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      1, r2, r3);
3321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ---------- S t a t e --------------
33233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- lr     : return address
33243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r0     : key
33253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r1     : receiver
3326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
33273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
33283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
33293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(slow_ic, RelocInfo::CODE_TARGET);
3330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Miss case, call the runtime.
33323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
3333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ---------- S t a t e --------------
33353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- lr     : return address
33363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r0     : key
33373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r1     : receiver
33383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
3339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_ic =
33413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
33423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
33433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
3344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3346589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochstatic bool IsElementTypeSigned(ElementsKind elements_kind) {
33473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
3349589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
3350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
33511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      return true;
33521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3353589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3354589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3356589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
33571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      return false;
33581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3359589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
3360589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
3361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_ELEMENTS:
33623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case FAST_SMI_ONLY_ELEMENTS:
3363589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_DOUBLE_ELEMENTS:
3364589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case DICTIONARY_ELEMENTS:
3365589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case NON_STRICT_ARGUMENTS_ELEMENTS:
33661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
33671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      return false;
33681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
33693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return false;
33701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
33711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray(
3374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3375589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
33761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------- S t a t e --------------
33771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- lr     : return address
33781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r0     : key
33791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r1     : receiver
33801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
3381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic, slow, failed_allocation;
33821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register key = r0;
33841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register receiver = r1;
33851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
33881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the key is a smi.
3390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(key, &miss_force_generic);
33911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
339344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // r3: elements array
33941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the index is in range.
33961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
339769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmp(key, ip);
33981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
339969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ b(hs, &miss_force_generic);
34001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
34021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r3: base pointer of external storage
34031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We are not untagging smi key and instead work with it
34051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // as if it was premultiplied by 2.
340669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
34071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register value = r2;
34093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
34111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ ldrsb(value, MemOperand(r3, key, LSR, 1));
34121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3413589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
3414589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ ldrb(value, MemOperand(r3, key, LSR, 1));
34161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3417589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ ldrsh(value, MemOperand(r3, key, LSL, 0));
34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3420589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
34211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ ldrh(value, MemOperand(r3, key, LSL, 0));
34221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3423589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
3424589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
34251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ ldr(value, MemOperand(r3, key, LSL, 1));
34261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
34288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (CpuFeatures::IsSupported(VFP3)) {
34291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        CpuFeatures::Scope scope(VFP3);
34301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ add(r2, r3, Operand(key, LSL, 1));
34311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ vldr(s0, r2, 0);
34321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
34331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ ldr(value, MemOperand(r3, key, LSL, 1));
34341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
34351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3436589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
3437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (CpuFeatures::IsSupported(VFP3)) {
3438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        CpuFeatures::Scope scope(VFP3);
3439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ add(r2, r3, Operand(key, LSL, 2));
3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ vldr(d0, r2, 0);
3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ add(r4, r3, Operand(key, LSL, 2));
3443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // r4: pointer to the beginning of the double we want to load.
3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ ldr(r2, MemOperand(r4, 0));
3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ ldr(r3, MemOperand(r4, Register::kSizeInBytes));
3446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
3447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3448589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_ELEMENTS:
34493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case FAST_SMI_ONLY_ELEMENTS:
3450589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_DOUBLE_ELEMENTS:
3451589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case DICTIONARY_ELEMENTS:
3452589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case NON_STRICT_ARGUMENTS_ELEMENTS:
34531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
34541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
34551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
34561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For integer array types:
34581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r2: value
3459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // For float array type:
34601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // s0: value (if VFP3 is supported)
34611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r2: value (if VFP3 is not supported)
3462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // For double array type:
3463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // d0: value (if VFP3 is supported)
3464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // r2/r3: value (if VFP3 is not supported)
34651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3466589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_INT_ELEMENTS) {
34671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the Int and UnsignedInt array types, we need to see whether
34681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // the value can be represented in a Smi. If not, we need to convert
34691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // it to a HeapNumber.
34701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Label box_int;
34711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmp(value, Operand(0xC0000000));
34721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(mi, &box_int);
34731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Tag integer as smi and return it.
34741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(r0, Operand(value, LSL, kSmiTagSize));
34751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Ret();
34761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&box_int);
34781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Allocate a HeapNumber for the result and perform int-to-double
34791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // conversion.  Don't touch r0 or r1 as they are needed if allocation
34801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // fails.
34811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
34821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ AllocateHeapNumber(r5, r3, r4, r6, &slow);
34831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Now we can use r0 for the result as key is not needed any more.
34841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(r0, r5);
34851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (CpuFeatures::IsSupported(VFP3)) {
34871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      CpuFeatures::Scope scope(VFP3);
34881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vmov(s0, value);
34891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vcvt_f64_s32(d0, s0);
34901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ sub(r3, r0, Operand(kHeapObjectTag));
34911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vstr(d0, r3, HeapNumber::kValueOffset);
34921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
34931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
3494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Register dst1 = r1;
3495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Register dst2 = r3;
3496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FloatingPointHelper::Destination dest =
3497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          FloatingPointHelper::kCoreRegisters;
3498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FloatingPointHelper::ConvertIntToDouble(masm,
3499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              value,
3500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              dest,
3501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              d0,
3502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              dst1,
3503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              dst2,
3504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              r9,
3505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              s0);
3506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ str(dst1, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
3507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ str(dst2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
3508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
35091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
3510589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
35111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // The test is different for unsigned int values. Since we need
35121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // the value to be in the range of a positive smi, we can't
35131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // handle either of the top two bits being set in the value.
35148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (CpuFeatures::IsSupported(VFP3)) {
35151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      CpuFeatures::Scope scope(VFP3);
35161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Label box_int, done;
35171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ tst(value, Operand(0xC0000000));
35181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ b(ne, &box_int);
35191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Tag integer as smi and return it.
35201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, Operand(value, LSL, kSmiTagSize));
35211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
35221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&box_int);
35241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vmov(s0, value);
35251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Allocate a HeapNumber for the result and perform int-to-double
35261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // conversion. Don't use r0 and r1 as AllocateHeapNumber clobbers all
35271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // registers - also when jumping due to exhausted young space.
35281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
35291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ AllocateHeapNumber(r2, r3, r4, r6, &slow);
35301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vcvt_f64_u32(d0, s0);
35321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ sub(r1, r2, Operand(kHeapObjectTag));
35331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vstr(d0, r1, HeapNumber::kValueOffset);
35341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, r2);
35361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
35371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
35381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Check whether unsigned integer fits into smi.
35391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Label box_int_0, box_int_1, done;
35401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ tst(value, Operand(0x80000000));
35411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ b(ne, &box_int_0);
35421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ tst(value, Operand(0x40000000));
35431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ b(ne, &box_int_1);
35441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Tag integer as smi and return it.
35451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, Operand(value, LSL, kSmiTagSize));
35461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
35471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Register hiword = value;  // r2.
35491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Register loword = r3;
35501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&box_int_0);
35521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Integer does not have leading zeros.
3553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      GenerateUInt2Double(masm, hiword, loword, r4, 0);
35541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ b(&done);
35551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&box_int_1);
35571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Integer has one leading zero.
3558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      GenerateUInt2Double(masm, hiword, loword, r4, 1);
35591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&done);
35621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Integer was converted to double in registers hiword:loword.
35631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber
35641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // clobbers all registers - also when jumping due to exhausted young
35651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // space.
35661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
35671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ AllocateHeapNumber(r4, r5, r7, r6, &slow);
35681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ str(hiword, FieldMemOperand(r4, HeapNumber::kExponentOffset));
35701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ str(loword, FieldMemOperand(r4, HeapNumber::kMantissaOffset));
35711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, r4);
35731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
35741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
3575589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
35761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the floating-point array type, we need to always allocate a
35771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // HeapNumber.
35788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (CpuFeatures::IsSupported(VFP3)) {
35791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      CpuFeatures::Scope scope(VFP3);
35801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Allocate a HeapNumber for the result. Don't use r0 and r1 as
35811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // AllocateHeapNumber clobbers all registers - also when jumping due to
35821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // exhausted young space.
35831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
35841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ AllocateHeapNumber(r2, r3, r4, r6, &slow);
35851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vcvt_f64_f32(d0, s0);
35861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ sub(r1, r2, Operand(kHeapObjectTag));
35871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vstr(d0, r1, HeapNumber::kValueOffset);
35881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, r2);
35901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
35911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
35921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Allocate a HeapNumber for the result. Don't use r0 and r1 as
35931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // AllocateHeapNumber clobbers all registers - also when jumping due to
35941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // exhausted young space.
35951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
35961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ AllocateHeapNumber(r3, r4, r5, r6, &slow);
35971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // VFP is not available, do manual single to double conversion.
35981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // r2: floating point value (binary32)
36001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // r3: heap number for result
36011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Extract mantissa to r0. OK to clobber r0 now as there are no jumps to
36031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // the slow case from here.
36041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ and_(r0, value, Operand(kBinary32MantissaMask));
36051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Extract exponent to r1. OK to clobber r1 now as there are no jumps to
36071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // the slow case from here.
36081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r1, Operand(value, LSR, kBinary32MantissaBits));
36091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ and_(r1, r1, Operand(kBinary32ExponentMask >> kBinary32MantissaBits));
36101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Label exponent_rebiased;
36121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ teq(r1, Operand(0x00));
36131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ b(eq, &exponent_rebiased);
36141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ teq(r1, Operand(0xff));
36161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r1, Operand(0x7ff), LeaveCC, eq);
36171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ b(eq, &exponent_rebiased);
36181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Rebias exponent.
36201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ add(r1,
36211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block             r1,
36221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block             Operand(-kBinary32ExponentBias + HeapNumber::kExponentBias));
36231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&exponent_rebiased);
36251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ and_(r2, value, Operand(kBinary32SignMask));
36261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      value = no_reg;
36271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ orr(r2, r2, Operand(r1, LSL, HeapNumber::kMantissaBitsInTopWord));
36281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Shift mantissa.
36301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      static const int kMantissaShiftForHiWord =
36311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
36321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      static const int kMantissaShiftForLoWord =
36341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          kBitsPerInt - kMantissaShiftForHiWord;
36351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ orr(r2, r2, Operand(r0, LSR, kMantissaShiftForHiWord));
36371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, Operand(r0, LSL, kMantissaShiftForLoWord));
36381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ str(r2, FieldMemOperand(r3, HeapNumber::kExponentOffset));
36401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ str(r0, FieldMemOperand(r3, HeapNumber::kMantissaOffset));
36411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, r3);
36431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
36441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
3645589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (CpuFeatures::IsSupported(VFP3)) {
3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CpuFeatures::Scope scope(VFP3);
3648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Allocate a HeapNumber for the result. Don't use r0 and r1 as
3649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // AllocateHeapNumber clobbers all registers - also when jumping due to
3650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // exhausted young space.
3651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
3652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ AllocateHeapNumber(r2, r3, r4, r6, &slow);
3653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sub(r1, r2, Operand(kHeapObjectTag));
3654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ vstr(d0, r1, HeapNumber::kValueOffset);
3655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ mov(r0, r2);
3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Allocate a HeapNumber for the result. Don't use r0 and r1 as
3660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // AllocateHeapNumber clobbers all registers - also when jumping due to
3661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // exhausted young space.
3662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ LoadRoot(r7, Heap::kHeapNumberMapRootIndex);
3663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ AllocateHeapNumber(r4, r5, r6, r7, &slow);
3664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ str(r2, FieldMemOperand(r4, HeapNumber::kMantissaOffset));
3666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ str(r3, FieldMemOperand(r4, HeapNumber::kExponentOffset));
3667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ mov(r0, r4);
3668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
36701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
36721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Tag integer as smi and return it.
36731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(r0, Operand(value, LSL, kSmiTagSize));
36741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Ret();
36751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
36761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Slow case, key and receiver still in r0 and r1.
36781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
367944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(
3680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->counters()->keyed_load_external_array_slow(),
368144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      1, r2, r3);
36821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------- S t a t e --------------
36841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- lr     : return address
36851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r0     : key
36861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r1     : receiver
36871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
36881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ Push(r1, r0);
36901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
36921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
36943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub =
36953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
36963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(stub, RelocInfo::CODE_TARGET);
36971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
36981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray(
3701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3702589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
37031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------- S t a t e --------------
37041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r0     : value
37051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r1     : key
37061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r2     : receiver
37071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- lr     : return address
37081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
3709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label slow, check_heap_number, miss_force_generic;
37101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Register usage.
37121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register value = r0;
37131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register key = r1;
37141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register receiver = r2;
37151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r3 mostly holds the elements array or the destination external array.
37161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
37191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the key is a smi.
3721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(key, &miss_force_generic);
37221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
372369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
372469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
372544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the index is in range
37261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
372769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmp(key, ip);
37281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
3729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ b(hs, &miss_force_generic);
37301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Handle both smis and HeapNumbers in the fast path. Go to the
37321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // runtime for all other kinds of values.
37331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r3: external array.
3734589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
373544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Double to pixel conversion is only implemented in the runtime for now.
373644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ JumpIfNotSmi(value, &slow);
373744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
373844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ JumpIfNotSmi(value, &check_heap_number);
373944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
374044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiUntag(r5, value);
37411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
37421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r3: base pointer of external storage.
37441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r5: value (integer).
37453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3746589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
374744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Clamp the value to [0..255].
374844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ Usat(r5, 8, Operand(r5));
374969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ strb(r5, MemOperand(r3, key, LSR, 1));
375044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
3751589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
3752589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
375369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ strb(r5, MemOperand(r3, key, LSR, 1));
37541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3755589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
3756589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
375769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ strh(r5, MemOperand(r3, key, LSL, 0));
37581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3759589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
3760589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
376169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ str(r5, MemOperand(r3, key, LSL, 1));
37621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3763589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
37641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Perform int-to-float conversion and store to memory.
376569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(r4, key);
3766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9);
3767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3768589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
376969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ add(r3, r3, Operand(key, LSL, 2));
3770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // r3: effective address of the double element
3771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FloatingPointHelper::Destination destination;
3772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (CpuFeatures::IsSupported(VFP3)) {
3773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        destination = FloatingPointHelper::kVFPRegisters;
3774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
3775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        destination = FloatingPointHelper::kCoreRegisters;
3776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
3777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FloatingPointHelper::ConvertIntToDouble(
3778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          masm, r5, destination,
3779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          d0, r6, r7,  // These are: double_dst, dst1, dst2.
3780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          r4, s2);  // These are: scratch2, single_scratch.
3781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (destination == FloatingPointHelper::kVFPRegisters) {
3782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        CpuFeatures::Scope scope(VFP3);
3783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ vstr(d0, r3, 0);
3784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
3785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ str(r6, MemOperand(r3, 0));
3786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ str(r7, MemOperand(r3, Register::kSizeInBytes));
3787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
37881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3789589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_ELEMENTS:
37903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case FAST_SMI_ONLY_ELEMENTS:
3791589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_DOUBLE_ELEMENTS:
3792589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case DICTIONARY_ELEMENTS:
3793589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case NON_STRICT_ARGUMENTS_ELEMENTS:
37941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
37951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
37961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
37971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Entry registers are intact, r0 holds the value which is the return value.
37991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ Ret();
38001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3801589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
380244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // r3: external array.
380344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ bind(&check_heap_number);
380444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE);
380544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ b(ne, &slow);
38061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
380744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
38081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
380944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // r3: base pointer of external storage.
38101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
381144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The WebGL specification leaves the behavior of storing NaN and
381244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // +/-Infinity into integer arrays basically undefined. For more
381344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // reproducible behavior, convert these to zero.
38148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (CpuFeatures::IsSupported(VFP3)) {
381544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      CpuFeatures::Scope scope(VFP3);
38161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3817589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
381844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // vldr requires offset to be a multiple of 4 so we can not
381944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // include -kHeapObjectTag into it.
382044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ sub(r5, r0, Operand(kHeapObjectTag));
382144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ vldr(d0, r5, HeapNumber::kValueOffset);
382269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ add(r5, r3, Operand(key, LSL, 1));
382344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ vcvt_f32_f64(s0, d0);
382444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ vstr(s0, r5, 0);
3825589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sub(r5, r0, Operand(kHeapObjectTag));
3827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ vldr(d0, r5, HeapNumber::kValueOffset);
382869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ add(r5, r3, Operand(key, LSL, 2));
3829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ vstr(d0, r5, 0);
38301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
383144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // Hoisted load.  vldr requires offset to be a multiple of 4 so we can
383244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // not include -kHeapObjectTag into it.
383344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ sub(r5, value, Operand(kHeapObjectTag));
383444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ vldr(d0, r5, HeapNumber::kValueOffset);
38353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        __ EmitECMATruncate(r5, d0, s2, r6, r7, r9);
383644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
38373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        switch (elements_kind) {
3838589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_BYTE_ELEMENTS:
3839589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
384069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ strb(r5, MemOperand(r3, key, LSR, 1));
384144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
3842589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_SHORT_ELEMENTS:
3843589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
384469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ strh(r5, MemOperand(r3, key, LSL, 0));
384544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
3846589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_INT_ELEMENTS:
3847589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_INT_ELEMENTS:
384869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ str(r5, MemOperand(r3, key, LSL, 1));
384944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
3850589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_PIXEL_ELEMENTS:
3851589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_FLOAT_ELEMENTS:
3852589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_DOUBLE_ELEMENTS:
3853589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case FAST_ELEMENTS:
38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          case FAST_SMI_ONLY_ELEMENTS:
3855589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case FAST_DOUBLE_ELEMENTS:
3856589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case DICTIONARY_ELEMENTS:
3857589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case NON_STRICT_ARGUMENTS_ELEMENTS:
385844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            UNREACHABLE();
385944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
386044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
38611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
38621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
38631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Entry registers are intact, r0 holds the value which is the return
38641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // value.
38651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
38661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
386744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // VFP3 is not available do manual conversions.
386844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset));
386944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset));
387044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3871589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
387244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Label done, nan_or_infinity_or_zero;
387344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        static const int kMantissaInHiWordShift =
387444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
387544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
387644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        static const int kMantissaInLoWordShift =
387744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            kBitsPerInt - kMantissaInHiWordShift;
387844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
387944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // Test for all special exponent values: zeros, subnormal numbers, NaNs
388044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // and infinities. All these should be converted to 0.
388144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r7, Operand(HeapNumber::kExponentMask));
388244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r9, r5, Operand(r7), SetCC);
388344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(eq, &nan_or_infinity_or_zero);
388444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
388544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ teq(r9, Operand(r7));
388644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r9, Operand(kBinary32ExponentMask), LeaveCC, eq);
388744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(eq, &nan_or_infinity_or_zero);
388844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
388944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // Rebias exponent.
389044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
389144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ add(r9,
389244f0eee88ff00398ff7f715fab053374d808c90dSteve Block               r9,
389344f0eee88ff00398ff7f715fab053374d808c90dSteve Block               Operand(kBinary32ExponentBias - HeapNumber::kExponentBias));
389444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
389544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ cmp(r9, Operand(kBinary32MaxExponent));
389644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, gt);
389744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r5, r5, Operand(kBinary32ExponentMask), LeaveCC, gt);
389844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(gt, &done);
389944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
390044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ cmp(r9, Operand(kBinary32MinExponent));
390144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, lt);
390244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(lt, &done);
390344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
390444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r7, r5, Operand(HeapNumber::kSignMask));
390544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
390644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r7, r7, Operand(r5, LSL, kMantissaInHiWordShift));
390744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r7, r7, Operand(r6, LSR, kMantissaInLoWordShift));
390844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r5, r7, Operand(r9, LSL, kBinary32ExponentShift));
390944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
391044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ bind(&done);
391169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ str(r5, MemOperand(r3, key, LSL, 1));
391244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // Entry registers are intact, r0 holds the value which is the return
391344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // value.
391444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ Ret();
391544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
391644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ bind(&nan_or_infinity_or_zero);
391744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r7, r5, Operand(HeapNumber::kSignMask));
391844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
391944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r9, r9, r7);
392044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift));
392144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift));
392244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(&done);
3923589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
392469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ add(r7, r3, Operand(key, LSL, 2));
3925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // r7: effective address of destination element.
3926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ str(r6, MemOperand(r7, 0));
3927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ str(r5, MemOperand(r7, Register::kSizeInBytes));
3928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Ret();
392944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else {
39303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        bool is_signed_type = IsElementTypeSigned(elements_kind);
393144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt;
393244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000;
393344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
393444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Label done, sign;
393544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
393644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // Test for all special exponent values: zeros, subnormal numbers, NaNs
393744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // and infinities. All these should be converted to 0.
393844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r7, Operand(HeapNumber::kExponentMask));
393944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r9, r5, Operand(r7), SetCC);
394044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
394144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(eq, &done);
394244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
394344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ teq(r9, Operand(r7));
394444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
394544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(eq, &done);
394644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
394744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // Unbias exponent.
394844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
394944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC);
395044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // If exponent is negative then result is 0.
395144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, mi);
395244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(mi, &done);
395344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
395444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // If exponent is too big then result is minimal value.
395544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ cmp(r9, Operand(meaningfull_bits - 1));
395644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r5, Operand(min_value), LeaveCC, ge);
395744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(ge, &done);
395844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
395944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r7, r5, Operand(HeapNumber::kSignMask), SetCC);
396044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
396144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r5, r5, Operand(1u << HeapNumber::kMantissaBitsInTopWord));
396244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
396344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ rsb(r9, r9, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC);
396444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl);
396544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(pl, &sign);
396644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
396744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ rsb(r9, r9, Operand(0, RelocInfo::NONE));
396844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r5, Operand(r5, LSL, r9));
396944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ rsb(r9, r9, Operand(meaningfull_bits));
397044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r5, r5, Operand(r6, LSR, r9));
397144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
397244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ bind(&sign);
397344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ teq(r7, Operand(0, RelocInfo::NONE));
397444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne);
397544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
397644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ bind(&done);
39773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        switch (elements_kind) {
3978589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_BYTE_ELEMENTS:
3979589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
398069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ strb(r5, MemOperand(r3, key, LSR, 1));
398144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
3982589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_SHORT_ELEMENTS:
3983589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
398469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ strh(r5, MemOperand(r3, key, LSL, 0));
398544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
3986589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_INT_ELEMENTS:
3987589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_INT_ELEMENTS:
398869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ str(r5, MemOperand(r3, key, LSL, 1));
398944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
3990589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_PIXEL_ELEMENTS:
3991589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_FLOAT_ELEMENTS:
3992589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_DOUBLE_ELEMENTS:
3993589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case FAST_ELEMENTS:
39943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          case FAST_SMI_ONLY_ELEMENTS:
3995589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case FAST_DOUBLE_ELEMENTS:
3996589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case DICTIONARY_ELEMENTS:
3997589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case NON_STRICT_ARGUMENTS_ELEMENTS:
399844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            UNREACHABLE();
399944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
400044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
40011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
40021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
40031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
40041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Slow case, key and receiver still in r0 and r1.
40061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
4007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(
4008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->counters()->keyed_load_external_array_slow(),
4009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      1, r2, r3);
40101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
40111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------- S t a t e --------------
40121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- lr     : return address
4013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r0     : key
4014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r1     : receiver
40151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
4016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> slow_ic =
4017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_Slow();
4018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(slow_ic, RelocInfo::CODE_TARGET);
40191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Miss case, call the runtime.
4021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
40221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ---------- S t a t e --------------
4024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- lr     : return address
4025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r0     : key
4026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r1     : receiver
4027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
4028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
4030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
4032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
4036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
4037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- lr    : return address
4038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r0    : key
4039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r1    : receiver
4040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
4041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic;
4042e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
4044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
40451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
4047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(r0, &miss_force_generic);
4048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array.
4050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
4051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AssertFastElements(r2);
4052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is within bounds.
4054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r3, FieldMemOperand(r2, FixedArray::kLengthOffset));
4055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmp(r0, Operand(r3));
4056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ b(hs, &miss_force_generic);
4057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the result and make sure it's not the hole.
4059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ add(r3, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
406069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
4061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r4,
4062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
4063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
4064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmp(r4, ip);
4065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ b(eq, &miss_force_generic);
4066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(r0, r4);
4067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
4068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
40703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub =
40713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
40723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(stub, RelocInfo::CODE_TARGET);
4073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
40763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
40773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
40783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
40793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- lr    : return address
40803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r0    : key
40813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r1    : receiver
40823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
40833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label miss_force_generic, slow_allocate_heapnumber;
40843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
40853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register key_reg = r0;
40863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register receiver_reg = r1;
40873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register elements_reg = r2;
40883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register heap_number_reg = r2;
40893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register indexed_double_offset = r3;
40903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register scratch = r4;
40913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register scratch2 = r5;
40923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register scratch3 = r6;
40933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register heap_number_map = r7;
40943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
40953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
40963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
40973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
40983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a smi.
40993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(key_reg, &miss_force_generic);
41003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the elements array.
41023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ldr(elements_reg,
41033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
41043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is within bounds.
41063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
41073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(key_reg, Operand(scratch));
41083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ b(hs, &miss_force_generic);
41093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Load the upper word of the double in the fixed array and test for NaN.
41113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ add(indexed_double_offset, elements_reg,
41123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
41133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t upper_32_offset = FixedArray::kHeaderSize + sizeof(kHoleNanLower32);
41143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ldr(scratch, FieldMemOperand(indexed_double_offset, upper_32_offset));
41153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(scratch, Operand(kHoleNanUpper32));
41163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ b(&miss_force_generic, eq);
41173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Non-NaN. Allocate a new heap number and copy the double value into it.
41193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
41203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AllocateHeapNumber(heap_number_reg, scratch2, scratch3,
41213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        heap_number_map, &slow_allocate_heapnumber);
41223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Don't need to reload the upper 32 bits of the double, it's already in
41243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // scratch.
41253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ str(scratch, FieldMemOperand(heap_number_reg,
41263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  HeapNumber::kExponentOffset));
41273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ldr(scratch, FieldMemOperand(indexed_double_offset,
41283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  FixedArray::kHeaderSize));
41293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ str(scratch, FieldMemOperand(heap_number_reg,
41303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  HeapNumber::kMantissaOffset));
41313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(r0, heap_number_reg);
41333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
41343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow_allocate_heapnumber);
41363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
41373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
41383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(slow_ic, RelocInfo::CODE_TARGET);
41393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
41413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_ic =
41423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
41433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
41443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
41453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement(
41483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
41493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
41503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind elements_kind,
41513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
4152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
4153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r0    : value
4154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r1    : key
4155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r2    : receiver
4156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- lr    : return address
4157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r3    : scratch
4158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r4    : scratch (elements)
4159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
41603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, transition_elements_kind, grow, slow;
41613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label finish_store, check_capacity;
4162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register value_reg = r0;
4164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register key_reg = r1;
4165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register receiver_reg = r2;
41663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = r4;
41673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register elements_reg = r3;
41683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register length_reg = r5;
41693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch2 = r6;
4170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
4172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
4173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
41753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(key_reg, &miss_force_generic);
4176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
41773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
41783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotSmi(value_reg, &transition_elements_kind);
41793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
418085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
418185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Check that the key is within bounds.
41823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(elements_reg,
41833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (is_js_array) {
4185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Compare smis.
4190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmp(key_reg, scratch);
41913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
41923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(hs, &grow);
41933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
41943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(hs, &miss_force_generic);
41953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
41973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Make sure elements is a fast element array, not 'cow'.
41983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(elements_reg,
41993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              scratch,
42003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Heap::kFixedArrayMapRootIndex,
42013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              &miss_force_generic,
42023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DONT_DO_SMI_CHECK);
42035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
42043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
42053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
42063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(scratch,
42073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           elements_reg,
42083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Operand(FixedArray::kHeaderSize - kHeapObjectTag));
42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
42103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(scratch,
42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           scratch,
42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
42133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(value_reg, MemOperand(scratch));
42143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
42153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(elements_kind == FAST_ELEMENTS);
42163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(scratch,
42173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           elements_reg,
42183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Operand(FixedArray::kHeaderSize - kHeapObjectTag));
42193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
42203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(scratch,
42213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           scratch,
42223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
42233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(value_reg, MemOperand(scratch));
42243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(receiver_reg, value_reg);
42253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWrite(elements_reg,  // Object.
42263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   scratch,       // Address.
42273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   receiver_reg,  // Value.
42283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   kLRHasNotBeenSaved,
42293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   kDontSaveFPRegs);
42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // value_reg (r0) is preserved.
4232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Done.
4233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
4234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
4236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic =
4237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
42393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
42413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
42423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(ic_miss, RelocInfo::CODE_TARGET);
42433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
42453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array by a single element if possible.
42463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
42473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime. Flags already set by previous compare.
42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &miss_force_generic);
42513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(length_reg,
42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(elements_reg,
42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(elements_reg, Heap::kEmptyFixedArrayRootIndex);
42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &check_capacity);
42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, elements_reg, scratch, scratch2, &slow,
42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          TAG_OBJECT);
42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(scratch, FieldMemOperand(elements_reg, JSObject::kMapOffset));
42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(scratch, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(scratch, FieldMemOperand(elements_reg, FixedArray::SizeFor(i)));
42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
42733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Store the element at index zero.
42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(value_reg, FieldMemOperand(elements_reg, FixedArray::SizeFor(0)));
42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(elements_reg,
42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg,
42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch, kLRHasNotBeenSaved, kDontSaveFPRegs,
42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(length_reg, Operand(Smi::FromInt(1)));
42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Ret();
42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for cow elements, in general they are not handled by this stub
42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CheckMap(elements_reg,
42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                scratch,
42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Heap::kFixedCOWArrayMapRootIndex,
42943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &miss_force_generic,
42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                DONT_DO_SMI_CHECK);
42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(length_reg, scratch);
42993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(hs, &slow);
43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(length_reg, length_reg, Operand(Smi::FromInt(1)));
43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Jump(ic_slow, RelocInfo::CODE_TARGET);
43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
43111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
43121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
43133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
43143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm,
43153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
43173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
43183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r0    : value
43193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r1    : key
43203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r2    : receiver
43213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- lr    : return address
43223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r3    : scratch
43233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r4    : scratch
43243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r5    : scratch
43253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
43263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, transition_elements_kind, grow, slow;
43273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label finish_store, check_capacity;
43283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register value_reg = r0;
43303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register key_reg = r1;
43313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register receiver_reg = r2;
43323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register elements_reg = r3;
43333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch1 = r4;
43343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch2 = r5;
43353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch3 = r6;
43363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register scratch4 = r7;
43373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register length_reg = r7;
43383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
43403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
43413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(key_reg, &miss_force_generic);
43423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ldr(elements_reg,
43443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
43453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is within bounds.
43473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (is_js_array) {
43483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
43493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
43503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(scratch1,
43513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
43523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
43533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compare smis, unsigned compare catches both negative and out-of-bound
43543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // indexes.
43553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(key_reg, scratch1);
43563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (grow_mode == ALLOW_JSARRAY_GROWTH) {
43573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(hs, &grow);
43585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  } else {
43593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(hs, &miss_force_generic);
43605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
43613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
43633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreNumberToDoubleElements(value_reg,
43643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 key_reg,
43653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 receiver_reg,
43663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 elements_reg,
43673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch1,
43683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch2,
43693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch3,
43703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch4,
43713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 &transition_elements_kind);
43723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
43733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Handle store cache miss, replacing the ic with the generic stub.
43753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
43763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> ic =
43773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
43783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
43793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
43813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
43823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(ic_miss, RelocInfo::CODE_TARGET);
43833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
43853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array by a single element if possible.
43863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
43873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
43893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime. Flags already set by previous compare.
43903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &miss_force_generic);
43913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Transition on values that can't be stored in a FixedDoubleArray.
43933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label value_is_smi;
43943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(value_reg, &value_is_smi);
43953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
43963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(scratch1, Heap::kHeapNumberMapRootIndex);
43973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &transition_elements_kind);
43983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&value_is_smi);
43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
44013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
44023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(length_reg,
44033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
44043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(elements_reg,
44053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
44063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(elements_reg, Heap::kEmptyFixedArrayRootIndex);
44073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &check_capacity);
44083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
44103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, elements_reg, scratch1, scratch2, &slow,
44113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          TAG_OBJECT);
44123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Initialize the new FixedDoubleArray. Leave elements unitialized for
44143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // efficiency, they are guaranteed to be initialized before use.
44153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(scratch1, Heap::kFixedDoubleArrayMapRootIndex);
44163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(scratch1, FieldMemOperand(elements_reg, JSObject::kMapOffset));
44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(scratch1,
44183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
44193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(scratch1,
44203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset));
44213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
44233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(elements_reg,
44243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
44253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg,
44263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch1, kLRHasNotBeenSaved, kDontSaveFPRegs,
44273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
44283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
44303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(length_reg, Operand(Smi::FromInt(1)));
44313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
44323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
44333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
44353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
44363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(scratch1,
44373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset));
44383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(length_reg, scratch1);
44393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(hs, &slow);
44403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
44423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(length_reg, length_reg, Operand(Smi::FromInt(1)));
44433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
44443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
44453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
44473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
44483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Jump(ic_slow, RelocInfo::CODE_TARGET);
44493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
44503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
44513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
44523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
4454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
4456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
4458