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
12695710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    // Preserve the receiver register explicitly whenever it is different from
12705710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    // the holder and it is needed should the interceptor return without any
12715710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    // result. The CALLBACKS case needs the receiver to be passed into C++ code,
12725710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    // the FIELD case might cause a miss during the prototype check.
12735710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
12745710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    bool must_preserve_receiver_reg = !receiver.is(holder_reg) &&
12755710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch        (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
12765710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch
12777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Save necessary data before invoking an interceptor.
12787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Requires a frame to make GC aware of pushed pointers.
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FrameScope frame_scope(masm(), StackFrame::INTERNAL);
12815710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch      if (must_preserve_receiver_reg) {
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Push(receiver, holder_reg, name_reg);
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Push(holder_reg, name_reg);
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Invoke an interceptor.  Note: map checks from receiver to
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // interceptor's holder has been compiled before (see a caller
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // of this method.)
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCallLoadPropertyWithInterceptor(masm(),
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             receiver,
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder_reg,
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             name_reg,
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             interceptor_holder);
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if interceptor provided a value for property.  If it's
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the case, return immediately.
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label interceptor_failed;
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex);
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(r0, scratch1);
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ b(eq, &interceptor_failed);
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      frame_scope.GenerateLeaveFrame();
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Ret();
130285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&interceptor_failed);
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(name_reg);
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(holder_reg);
13065710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch      if (must_preserve_receiver_reg) {
13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ pop(receiver);
13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Leave the internal frame.
131085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    }
13117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps from interceptor's holder to lookup's holder
13127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // haven't changed.  And load lookup's holder into |holder| register.
13135710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    if (must_perfrom_prototype_check) {
13147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      holder_reg = CheckPrototypes(interceptor_holder,
13157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   holder_reg,
13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Handle<JSObject>(lookup->holder()),
13177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch1,
13187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch2,
13193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                   scratch3,
13207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   name,
13217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   miss);
13227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
13237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == FIELD) {
13257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found FIELD property in prototype chain of interceptor's holder.
13267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Retrieve a field from field's holder.
13277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      GenerateFastPropertyLoad(masm(), r0, holder_reg,
13283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Handle<JSObject>(lookup->holder()),
13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               lookup->GetFieldIndex());
13307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ Ret();
13317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
13327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found CALLBACKS property in prototype chain of interceptor's
13337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // holder.
13347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(lookup->type() == CALLBACKS);
13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<AccessorInfo> callback(
13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject()));
13377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(callback->getter() != NULL);
13387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Tail call to runtime.
13407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Important invariant in CALLBACKS case: the code above must be
13417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // structured to never clobber |receiver| register.
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Move(scratch2, callback);
13437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // holder_reg is either receiver or scratch1.
13447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      if (!receiver.is(holder_reg)) {
13457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        ASSERT(scratch1.is(holder_reg));
13468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ Push(receiver, holder_reg);
13478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ ldr(scratch3,
13488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang               FieldMemOperand(scratch2, AccessorInfo::kDataOffset));
13498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ Push(scratch3, scratch2, name_reg);
13507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      } else {
13517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        __ push(receiver);
13528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ ldr(scratch3,
13538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang               FieldMemOperand(scratch2, AccessorInfo::kDataOffset));
13548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ Push(holder_reg, scratch3, scratch2, name_reg);
13557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      }
13567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ExternalReference ref =
135844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
135944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            masm()->isolate());
13607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ TailCallExternalReference(ref, 5, 1);
13617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
13627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {  // !compile_followup_inline
13637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Call the runtime system to load the interceptor.
13647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps haven't changed.
13657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
13663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          scratch1, scratch2, scratch3,
13673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          name, miss);
13687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    PushInterceptorArguments(masm(), receiver, holder_reg,
13697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                             name_reg, interceptor_holder);
13707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
137144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExternalReference ref =
137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
137344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          masm()->isolate());
13747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ TailCallExternalReference(ref, 5, 1);
13757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
13809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (kind_ == Code::KEYED_CALL_IC) {
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(r2, Operand(name));
13829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ b(ne, miss);
13839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
13849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
13859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
13869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
139059151504615d929945dc59db37bf1166937748c6Steve Block                                                   Label* miss) {
139159151504615d929945dc59db37bf1166937748c6Steve Block  ASSERT(holder->IsGlobalObject());
139259151504615d929945dc59db37bf1166937748c6Steve Block
139359151504615d929945dc59db37bf1166937748c6Steve Block  // Get the number of arguments.
139459151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
139559151504615d929945dc59db37bf1166937748c6Steve Block
139659151504615d929945dc59db37bf1166937748c6Steve Block  // Get the receiver from the stack.
139759151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
139859151504615d929945dc59db37bf1166937748c6Steve Block
139959151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the maps haven't changed.
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(r0, miss);
140159151504615d929945dc59db37bf1166937748c6Steve Block  CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss);
140259151504615d929945dc59db37bf1166937748c6Steve Block}
140359151504615d929945dc59db37bf1166937748c6Steve Block
140459151504615d929945dc59db37bf1166937748c6Steve Block
14053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell(
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* miss) {
140959151504615d929945dc59db37bf1166937748c6Steve Block  // Get the value from the cell.
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r3, Operand(cell));
141159151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
141259151504615d929945dc59db37bf1166937748c6Steve Block
141359151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the cell contains the same function.
14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (heap()->InNewSpace(*function)) {
141559151504615d929945dc59db37bf1166937748c6Steve Block    // We can't embed a pointer to a function in new space so we have
141659151504615d929945dc59db37bf1166937748c6Steve Block    // to verify that the shared function info is unchanged. This has
141759151504615d929945dc59db37bf1166937748c6Steve Block    // the nice side effect that multiple closures based on the same
141859151504615d929945dc59db37bf1166937748c6Steve Block    // function can all use this call IC. Before we load through the
141959151504615d929945dc59db37bf1166937748c6Steve Block    // function, we have to verify that it still is a function.
14203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r1, miss);
142159151504615d929945dc59db37bf1166937748c6Steve Block    __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
142259151504615d929945dc59db37bf1166937748c6Steve Block    __ b(ne, miss);
142359151504615d929945dc59db37bf1166937748c6Steve Block
142459151504615d929945dc59db37bf1166937748c6Steve Block    // Check the shared function info. Make sure it hasn't changed.
142559151504615d929945dc59db37bf1166937748c6Steve Block    __ Move(r3, Handle<SharedFunctionInfo>(function->shared()));
142659151504615d929945dc59db37bf1166937748c6Steve Block    __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
142759151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(r4, r3);
142859151504615d929945dc59db37bf1166937748c6Steve Block  } else {
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(r1, Operand(function));
143059151504615d929945dc59db37bf1166937748c6Steve Block  }
14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(ne, miss);
143259151504615d929945dc59db37bf1166937748c6Steve Block}
143359151504615d929945dc59db37bf1166937748c6Steve Block
143459151504615d929945dc59db37bf1166937748c6Steve Block
14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() {
14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code =
1437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                               kind_,
14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               extra_state_);
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(code, RelocInfo::CODE_TARGET);
14417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
14427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
14465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                int index,
14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r2    : name
1450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- lr    : return address
1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
14559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver of the function from the stack into r0.
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
14613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r0, &miss);
1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do the right check and compute the holder register.
14643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss);
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall(
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
14856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r2    : name
14866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- lr    : return address
14878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
14888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- ...
14898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[argc * 4]           : receiver
14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
14916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
149259151504615d929945dc59db37bf1166937748c6Steve Block  // If object is not an array, bail out to regular call.
14933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
14969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
14979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
14988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register receiver = r1;
14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack
15006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
15018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
15041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(receiver, &miss);
15056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the maps haven't changed.
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, r3, r0, r4,
15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, &miss);
15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (argc == 0) {
15118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    // Nothing to do, just return the length.
15128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
15138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Drop(argc + 1);
15148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Ret();
15158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  } else {
15168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    Label call_builtin;
15178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (argc == 1) {  // Otherwise fall through to call the builtin.
15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label attempt_to_grow_elements;
15208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register elements = r6;
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register end_elements = r5;
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements array of the object.
15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
15255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check that the elements are in fast mode and writable.
15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckMap(elements,
15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  r0,
15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Heap::kFixedArrayMapRootIndex,
15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  &call_builtin,
15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  DONT_DO_SMI_CHECK);
15325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
15335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
15348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Get the array's length into r0 and calculate new length.
15358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
15368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      STATIC_ASSERT(kSmiTagSize == 1);
15378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      STATIC_ASSERT(kSmiTag == 0);
15388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(r0, r0, Operand(Smi::FromInt(argc)));
15398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements' length.
15418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
15428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Check if we could survive without allocation.
15448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ cmp(r0, r4);
15458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ b(gt, &attempt_to_grow_elements);
15468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if value is a smi.
15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label with_write_barrier;
15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfNotSmi(r4, &with_write_barrier);
15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Save new length.
15538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
15548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
15568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // We may need a register containing the address end_elements below,
15578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // so write back the value in end_elements.
15588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(end_elements, elements,
15598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang             Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
15608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      const int kEndElementsOffset =
15618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang          FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
15628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
15638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Check for a smi.
15658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Drop(argc + 1);
15668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Ret();
15678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ bind(&with_write_barrier);
15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset));
15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_smi_only_arrays  && !FLAG_trace_elements_transitions) {
15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label fast_object, not_fast_object;
15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(r3, r7, &not_fast_object);
15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&fast_object);
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // In case of fast smi-only, convert to fast object, otherwise bail out.
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&not_fast_object);
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastSmiOnlyElements(r3, r7, &call_builtin);
15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // edx: receiver
15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // r3: map
15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               FAST_ELEMENTS,
15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               r3,
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               r7,
15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               &call_builtin);
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(r2, receiver);
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm());
15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&fast_object);
15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(r3, r3, &call_builtin);
15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Save new length.
15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // We may need a register containing the address end_elements below,
15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // so write back the value in end_elements.
15993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(end_elements, elements,
16003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
16013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWrite(elements,
16043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     end_elements,
16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     r4,
16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     kLRHasNotBeenSaved,
16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     kDontSaveFPRegs,
16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     EMIT_REMEMBERED_SET,
16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     OMIT_SMI_CHECK);
16108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Drop(argc + 1);
16118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Ret();
16128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ bind(&attempt_to_grow_elements);
16148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // r0: array's length + 1.
16158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // r4: elements' length.
16168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      if (!FLAG_inline_new) {
16188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ b(&call_builtin);
16198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      }
16208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r2, MemOperand(sp, (argc - 1) * kPointerSize));
16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Growing elements that are SMI-only requires special handling in case
16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the new element is non-Smi. For now, delegate to the builtin.
16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label no_fast_elements_check;
16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfSmi(r2, &no_fast_elements_check);
16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r7, FieldMemOperand(receiver, HeapObject::kMapOffset));
16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckFastObjectElements(r7, r7, &call_builtin);
16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&no_fast_elements_check);
16293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
163044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate* isolate = masm()->isolate();
16318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      ExternalReference new_space_allocation_top =
163244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_top_address(isolate);
16338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      ExternalReference new_space_allocation_limit =
163444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_limit_address(isolate);
16358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      const int kAllocationDelta = 4;
16378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Load top and check if it is the end of elements.
16388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(end_elements, elements,
16398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang             Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
16408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(end_elements, end_elements, Operand(kEndElementsOffset));
16418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ mov(r7, Operand(new_space_allocation_top));
16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r3, MemOperand(r7));
16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(end_elements, r3);
16448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ b(ne, &call_builtin);
16458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ mov(r9, Operand(new_space_allocation_limit));
16478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ ldr(r9, MemOperand(r9));
16483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(r3, r3, Operand(kAllocationDelta * kPointerSize));
16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(r3, r9);
16508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ b(hi, &call_builtin);
16518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // We fit and could grow elements.
16538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Update new_space_allocation_top.
16543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r3, MemOperand(r7));
16558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Push the argument.
16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r2, MemOperand(end_elements));
16578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Fill the rest with holes.
16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
16598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      for (int i = 1; i < kAllocationDelta; i++) {
16603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ str(r3, MemOperand(end_elements, i * kPointerSize));
16618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      }
16628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Update elements' and array's sizes.
16648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
16658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta)));
16668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
16678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
16688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Elements are in new space, so write barrier is not required.
16698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Drop(argc + 1);
16708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Ret();
16718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    }
16728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ bind(&call_builtin);
167344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
167444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                   masm()->isolate()),
16758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 argc + 1,
16768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 1);
16778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
16786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Handle call cache miss.
16806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
16813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
16826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
168425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
16856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
16866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16883ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall(
16893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
16903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
16913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
16923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
16933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1695402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r2    : name
1696402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- lr    : return address
16978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
16988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- ...
16998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[argc * 4]           : receiver
1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
17016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
170259151504615d929945dc59db37bf1166937748c6Steve Block  // If object is not an array, bail out to regular call.
17033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
17046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label miss, return_undefined, call_builtin;
17068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register receiver = r1;
17078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register elements = r3;
17089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
17099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
17128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
17141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(receiver, &miss);
17156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the maps haven't changed.
17173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, elements,
17183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  r4, r0, name, &miss);
17198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Get the elements array of the object.
17218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
17226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check that the elements are in fast mode and writable.
1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(elements,
1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              r0,
1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              Heap::kFixedArrayMapRootIndex,
1727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              &call_builtin,
1728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              DONT_DO_SMI_CHECK);
17298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Get the array's length into r4 and calculate new length.
17318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
17328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC);
17338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(lt, &return_undefined);
17348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Get the last element.
17368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
17378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(kSmiTagSize == 1);
17388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(kSmiTag == 0);
17398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We can't address the last element in one operation. Compute the more
17408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // expensive shift first, and use an offset later on.
17418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ add(elements, elements, Operand(r4, LSL, kPointerSizeLog2 - kSmiTagSize));
17428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r0, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag));
17438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(r0, r6);
17448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(eq, &call_builtin);
17458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Set the array's length.
17478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
17488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Fill with the hole.
17508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(r6, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag));
17518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(argc + 1);
17528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
17538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&return_undefined);
17558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
17568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(argc + 1);
17578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
17588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
17598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&call_builtin);
176044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop,
176144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 masm()->isolate()),
17626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               argc + 1,
17636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               1);
17646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Handle call cache miss.
17666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
17673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
17686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
177025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
17716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17743ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
17763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
17773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
17783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
17793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
178080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ----------- S t a t e -------------
178180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- r2                     : function name
178280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- lr                     : return address
178380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
178480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- ...
178580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- sp[argc * 4]           : receiver
178680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // -----------------------------------
178780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
178880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If object is not a string, bail out to regular call.
17893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
179080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
179180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const int argc = arguments().immediate();
179280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label miss;
1793b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
179480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label index_out_of_range;
1795b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
1796b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
17983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1800b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1801b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1802b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
180380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
180480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the maps starting from the prototype haven't changed.
180580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateDirectLoadGlobalFunctionPrototype(masm(),
180680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                            Context::STRING_FUNCTION_INDEX,
18070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            r0,
18080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
18093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
18103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
18113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  r0, holder, r1, r3, r4, name, &miss);
181280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
181380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register receiver = r1;
181480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register index = r4;
181580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register result = r0;
181680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
181780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (argc > 0) {
181880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
181980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
182080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
182180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
182280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharCodeAtGenerator generator(receiver,
18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index,
18253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      result,
18263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a string.
18273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a number.
18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index_out_of_range_label,
18293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      STRING_INDEX_IS_NUMBER);
18303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
183180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Drop(argc + 1);
183280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Ret();
183380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
18353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
183680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1837b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1838b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
1839b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ LoadRoot(r0, Heap::kNanValueRootIndex);
1840b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ Drop(argc + 1);
1841b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ Ret();
1842b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
184380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
184480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&miss);
1845b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in r2.
18463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(r2, name);
1847b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
184980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
185080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Return the generated code.
185180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return GetCode(function);
18527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
18537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall(
18563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
18573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
18583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
18593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
186180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ----------- S t a t e -------------
186280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- r2                     : function name
186380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- lr                     : return address
186480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
186580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- ...
186680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- sp[argc * 4]           : receiver
186780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // -----------------------------------
186880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
186980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If object is not a string, bail out to regular call.
18703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
187180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
187280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const int argc = arguments().immediate();
187380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label miss;
1874b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
187580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label index_out_of_range;
1876b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
1877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
18783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1880b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1881b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1882b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
188380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
188480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the maps starting from the prototype haven't changed.
188580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateDirectLoadGlobalFunctionPrototype(masm(),
188680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                            Context::STRING_FUNCTION_INDEX,
18870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            r0,
18880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
18903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
18913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  r0, holder, r1, r3, r4, name, &miss);
189280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
189380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register receiver = r0;
189480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register index = r4;
18953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = r3;
189680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register result = r0;
189780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
189880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (argc > 0) {
189980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
190080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
190180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
190280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
190380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
19043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharAtGenerator generator(receiver,
19053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index,
19063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  scratch,
19073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  result,
19083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a string.
19093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a number.
19103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index_out_of_range_label,
19113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  STRING_INDEX_IS_NUMBER);
19123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
191380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Drop(argc + 1);
191480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Ret();
191580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
19173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
191880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1919b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1920b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
1921b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ LoadRoot(r0, Heap::kEmptyStringRootIndex);
1922b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ Drop(argc + 1);
1923b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ Ret();
1924b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
192580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
192680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&miss);
1927b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in r2.
19283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(r2, name);
1929b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
193180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
193280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Return the generated code.
193380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return GetCode(function);
19347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
19357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
19367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
19373ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
19383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
19393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
19403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
19413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
19423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
194359151504615d929945dc59db37bf1166937748c6Steve Block  // ----------- S t a t e -------------
194459151504615d929945dc59db37bf1166937748c6Steve Block  //  -- r2                     : function name
194559151504615d929945dc59db37bf1166937748c6Steve Block  //  -- lr                     : return address
194659151504615d929945dc59db37bf1166937748c6Steve Block  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
194759151504615d929945dc59db37bf1166937748c6Steve Block  //  -- ...
194859151504615d929945dc59db37bf1166937748c6Steve Block  //  -- sp[argc * 4]           : receiver
194959151504615d929945dc59db37bf1166937748c6Steve Block  // -----------------------------------
195059151504615d929945dc59db37bf1166937748c6Steve Block
195159151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
195259151504615d929945dc59db37bf1166937748c6Steve Block
195359151504615d929945dc59db37bf1166937748c6Steve Block  // If the object is not a JSObject or we got an unexpected number of
195459151504615d929945dc59db37bf1166937748c6Steve Block  // arguments, bail out to the regular call.
19553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
195659151504615d929945dc59db37bf1166937748c6Steve Block
195759151504615d929945dc59db37bf1166937748c6Steve Block  Label miss;
195859151504615d929945dc59db37bf1166937748c6Steve Block  GenerateNameCheck(name, &miss);
195959151504615d929945dc59db37bf1166937748c6Steve Block
19603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
196159151504615d929945dc59db37bf1166937748c6Steve Block    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
196259151504615d929945dc59db37bf1166937748c6Steve Block
196359151504615d929945dc59db37bf1166937748c6Steve Block    STATIC_ASSERT(kSmiTag == 0);
19643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r1, &miss);
196559151504615d929945dc59db37bf1166937748c6Steve Block
19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4,
19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
196859151504615d929945dc59db37bf1166937748c6Steve Block  } else {
19693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
19703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
19713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
197259151504615d929945dc59db37bf1166937748c6Steve Block    GenerateLoadFunctionFromCell(cell, function, &miss);
197359151504615d929945dc59db37bf1166937748c6Steve Block  }
197459151504615d929945dc59db37bf1166937748c6Steve Block
197559151504615d929945dc59db37bf1166937748c6Steve Block  // Load the char code argument.
197659151504615d929945dc59db37bf1166937748c6Steve Block  Register code = r1;
197759151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(code, MemOperand(sp, 0 * kPointerSize));
197859151504615d929945dc59db37bf1166937748c6Steve Block
197959151504615d929945dc59db37bf1166937748c6Steve Block  // Check the code is a smi.
198059151504615d929945dc59db37bf1166937748c6Steve Block  Label slow;
198159151504615d929945dc59db37bf1166937748c6Steve Block  STATIC_ASSERT(kSmiTag == 0);
19823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(code, &slow);
198359151504615d929945dc59db37bf1166937748c6Steve Block
198459151504615d929945dc59db37bf1166937748c6Steve Block  // Convert the smi code to uint16.
198559151504615d929945dc59db37bf1166937748c6Steve Block  __ and_(code, code, Operand(Smi::FromInt(0xffff)));
198659151504615d929945dc59db37bf1166937748c6Steve Block
19873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharFromCodeGenerator generator(code, r0);
19883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
198959151504615d929945dc59db37bf1166937748c6Steve Block  __ Drop(argc + 1);
199059151504615d929945dc59db37bf1166937748c6Steve Block  __ Ret();
199159151504615d929945dc59db37bf1166937748c6Steve Block
1992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
199459151504615d929945dc59db37bf1166937748c6Steve Block
199559151504615d929945dc59db37bf1166937748c6Steve Block  // Tail call the full function. We do not have to patch the receiver
199659151504615d929945dc59db37bf1166937748c6Steve Block  // because the function makes no use of it.
199759151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&slow);
19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(
19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function,  arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
200059151504615d929945dc59db37bf1166937748c6Steve Block
200159151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&miss);
200259151504615d929945dc59db37bf1166937748c6Steve Block  // r2: function name.
20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
200459151504615d929945dc59db37bf1166937748c6Steve Block
200559151504615d929945dc59db37bf1166937748c6Steve Block  // Return the generated code.
20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
200759151504615d929945dc59db37bf1166937748c6Steve Block}
200859151504615d929945dc59db37bf1166937748c6Steve Block
200959151504615d929945dc59db37bf1166937748c6Steve Block
20103ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall(
20113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
20123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
20133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
20168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // ----------- S t a t e -------------
20178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- r2                     : function name
20188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- lr                     : return address
20198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
20208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- ...
20218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[argc * 4]           : receiver
20228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // -----------------------------------
20238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!CpuFeatures::IsSupported(VFP3)) {
20253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
202644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
202744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
20288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CpuFeatures::Scope scope_vfp3(VFP3);
20298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int argc = arguments().immediate();
20308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If the object is not a JSObject or we got an unexpected number of
20318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // arguments, bail out to the regular call.
20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
20338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label miss, slow;
20358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  GenerateNameCheck(name, &miss);
20368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
20388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
20398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    STATIC_ASSERT(kSmiTag == 0);
20401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ JumpIfSmi(r1, &miss);
20413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4,
20423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
20438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  } else {
20443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
20453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
20463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
20478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    GenerateLoadFunctionFromCell(cell, function, &miss);
20488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
20498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the (only) argument into r0.
20518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r0, MemOperand(sp, 0 * kPointerSize));
20528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If the argument is a smi, just return.
20548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(kSmiTag == 0);
20558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ tst(r0, Operand(kSmiTagMask));
20568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(argc + 1, eq);
20578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret(eq);
20588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
20608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label wont_fit_smi, no_vfp_exception, restore_fpscr_and_return;
20628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If vfp3 is enabled, we use the fpu rounding with the RM (round towards
20648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // minus infinity) mode.
20658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the HeapNumber value.
20678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We will need access to the value in the core registers, so we load it
20688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // with ldrd and move it to the fpu. It also spares a sub instruction for
20698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // updating the HeapNumber value address, as vldr expects a multiple
20708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // of 4 offset.
20718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ldrd(r4, r5, FieldMemOperand(r0, HeapNumber::kValueOffset));
20728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmov(d1, r4, r5);
20738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Backup FPSCR.
20758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmrs(r3);
20768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Set custom FPCSR:
20778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  - Set rounding mode to "Round towards Minus Infinity"
20783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    (i.e. bits [23:22] = 0b10).
20798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  - Clear vfp cumulative exception flags (bits [3:0]).
20808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  - Make sure Flush-to-zero mode control bit is unset (bit 22).
20818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bic(r9, r3,
20828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask));
20831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ orr(r9, r9, Operand(kRoundToMinusInf));
20848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmsr(r9);
20858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Convert the argument to an integer.
20871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
20888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Use vcvt latency to start checking for special cases.
20908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Get the argument exponent and clear the sign bit.
20918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bic(r6, r5, Operand(HeapNumber::kSignMask));
20928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(r6, Operand(r6, LSR, HeapNumber::kMantissaBitsInTopWord));
20938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Retrieve FPSCR and check for vfp exceptions.
20958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmrs(r9);
20968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ tst(r9, Operand(kVFPExceptionMask));
20978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&no_vfp_exception, eq);
20988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
20998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check for NaN, Infinity, and -Infinity.
21008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // They are invariant through a Math.Floor call, so just
21018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // return the original argument.
21028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ sub(r7, r6, Operand(HeapNumber::kExponentMask
21038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        >> HeapNumber::kMantissaBitsInTopWord), SetCC);
21048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&restore_fpscr_and_return, eq);
21058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We had an overflow or underflow in the conversion. Check if we
21068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // have a big exponent.
21078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(r7, Operand(HeapNumber::kMantissaBits));
21088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If greater or equal, the argument is already round and in r0.
21098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&restore_fpscr_and_return, ge);
2110b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ b(&wont_fit_smi);
21118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&no_vfp_exception);
21138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Move the result back to general purpose register r0.
21148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmov(r0, s0);
21158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check if the result fits into a smi.
21168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ add(r1, r0, Operand(0x40000000), SetCC);
21178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&wont_fit_smi, mi);
21188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Tag the result.
21198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(kSmiTag == 0);
21208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
21218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check for -0.
2123b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(r0, Operand(0, RelocInfo::NONE));
21248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&restore_fpscr_and_return, ne);
21258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // r5 already holds the HeapNumber exponent.
21268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ tst(r5, Operand(HeapNumber::kSignMask));
21278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If our HeapNumber is negative it was -0, so load its address and return.
21288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Else r0 is loaded with 0, so we can also just return.
21298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r0, MemOperand(sp, 0 * kPointerSize), ne);
21308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&restore_fpscr_and_return);
21328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Restore FPSCR and return.
21338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmsr(r3);
21348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(argc + 1);
21358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
21368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&wont_fit_smi);
21388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Restore FPCSR and fall to slow case.
21398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmsr(r3);
21408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2141b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&slow);
21428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Tail call the full function. We do not have to patch the receiver
21438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // because the function makes no use of it.
21443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(
21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
21468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&miss);
21488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // r2: function name.
21493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
21508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
21518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Return the generated code.
21523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
21530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
21540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
21550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
21563ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall(
21573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
21583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
21593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
21603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2162f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // ----------- S t a t e -------------
2163f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- r2                     : function name
2164f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- lr                     : return address
2165f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
2166f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- ...
2167f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- sp[argc * 4]           : receiver
2168f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // -----------------------------------
2169f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2170f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const int argc = arguments().immediate();
2171f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the object is not a JSObject or we got an unexpected number of
2172f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // arguments, bail out to the regular call.
21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2174f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2175f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label miss;
2176f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  GenerateNameCheck(name, &miss);
21773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
2178f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
2179f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
21803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r1, &miss);
21813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4,
21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
2183f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  } else {
21843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
21863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
2187f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    GenerateLoadFunctionFromCell(cell, function, &miss);
2188f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
2189f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2190f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Load the (only) argument into r0.
2191f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ldr(r0, MemOperand(sp, 0 * kPointerSize));
2192f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2193f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check if the argument is a smi.
2194f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label not_smi;
2195f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
21961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfNotSmi(r0, &not_smi);
2197f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2198f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Do bitwise not or do nothing depending on the sign of the
2199f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // argument.
2200f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ eor(r1, r0, Operand(r0, ASR, kBitsPerInt - 1));
2201f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2202f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Add 1 or do nothing depending on the sign of the argument.
2203f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ sub(r0, r1, Operand(r0, ASR, kBitsPerInt - 1), SetCC);
2204f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2205f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the result is still negative, go to the slow case.
2206f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // This only happens for the most negative smi.
2207f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label slow;
2208f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ b(mi, &slow);
2209f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2210f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Smi case done.
2211f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Drop(argc + 1);
2212f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Ret();
2213f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2214f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check if the argument is a heap number and load its exponent and
2215f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // sign.
2216f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&not_smi);
2217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
2218f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ldr(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset));
2219f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2220f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check the sign of the argument. If the argument is positive,
2221f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // just return it.
2222f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label negative_sign;
2223f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ tst(r1, Operand(HeapNumber::kSignMask));
2224f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ b(ne, &negative_sign);
2225f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Drop(argc + 1);
2226f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Ret();
2227f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2228f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the argument is negative, clear the sign, and return a new
2229f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // number.
2230f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&negative_sign);
2231f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ eor(r1, r1, Operand(HeapNumber::kSignMask));
2232f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
2233f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
2234f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ AllocateHeapNumber(r0, r4, r5, r6, &slow);
2235f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset));
2236f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
2237f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Drop(argc + 1);
2238f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Ret();
2239f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2240f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Tail call the full function. We do not have to patch the receiver
2241f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // because the function makes no use of it.
2242f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&slow);
22433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(
22443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
2245f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2246f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&miss);
2247f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // r2: function name.
22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2249f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2250f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Return the generated code.
22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
2252f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
2253f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2254f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall(
225644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    const CallOptimization& optimization,
22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
226244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
226344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
226444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(optimization.is_simple_api_call());
226544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Bail out if object is a global object as we don't want to
226644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // repatch it to global receiver.
22673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (object->IsGlobalObject()) return Handle<Code>::null();
22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!cell.is_null()) return Handle<Code>::null();
22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject()) return Handle<Code>::null();
227044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int depth = optimization.GetPrototypeDepthOfExpectedType(
22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<JSObject>::cast(object), holder);
22723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (depth == kInvalidProtoDepth) return Handle<Code>::null();
227344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
227444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss, miss_before_stack_reserved;
227544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss_before_stack_reserved);
227644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
227744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the receiver from the stack.
227844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int argc = arguments().immediate();
227944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
228044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
228144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the receiver isn't a smi.
22823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r1, &miss_before_stack_reserved);
228344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
228444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const(), 1, r0, r3);
228544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3);
228644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
228744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ReserveSpaceForFastApiCall(masm(), r0);
228844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
228944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the maps haven't changed and find a Holder as a side effect.
22903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, name,
229144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                  depth, &miss);
229244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
22933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateFastApiDirectCall(masm(), optimization, argc);
229444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
229544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss);
229644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  FreeSpaceForFastApiCall(masm());
229744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
229844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss_before_stack_reserved);
22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
230044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
230144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Return the generated code.
230244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return GetCode(function);
230344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
230444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
230544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
23063ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
23073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> function,
23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
23105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   CheckType check) {
23116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
23126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r2    : name
23136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- lr    : return address
23146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
231544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
23163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder,
23173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Handle<JSGlobalPropertyCell>::null(),
23183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          function, name);
23193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
23203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
23216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
23226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
232344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss;
232444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss);
23259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
23266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack
23276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
23286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
23296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
23306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check != NUMBER_CHECK) {
23323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r1, &miss);
2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that it's okay not to patch the on stack receiver
2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // unless we're doing a receiver map check.
2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (check) {
2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RECEIVER_MAP_CHECK:
234044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ IncrementCounter(masm()->isolate()->counters()->call_const(),
234144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          1, r0, r3);
23426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the maps haven't changed.
23443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4,
23453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      name, &miss);
2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Patch the receiver on the stack with the global proxy if
2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // necessary.
2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsGlobalObject()) {
2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ str(r3, MemOperand(sp, argc * kPointerSize));
2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case STRING_CHECK:
23563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a two-byte string or a symbol.
2358402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
23593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        __ b(ge, &miss);
2360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
23617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
23620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::STRING_FUNCTION_INDEX, r0, &miss);
23633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
23643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
23653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            r0, holder, r3, r1, r4, name, &miss);
23663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
236785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
236885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // requires boxing.
236985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        __ jmp(&miss);
23703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
23713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
23723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case NUMBER_CHECK:
23743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
2376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a smi or a heap number.
23773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        __ JumpIfSmi(r1, &fast);
2378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE);
2379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ b(ne, &miss);
2380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
2381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
23827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
23830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss);
23843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
23853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            r0, holder, r3, r1, r4, name, &miss);
23873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
238885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
238985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // requires boxing.
239085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        __ jmp(&miss);
23913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
23923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
23933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case BOOLEAN_CHECK:
23953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
2397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a boolean.
2398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ LoadRoot(ip, Heap::kTrueValueRootIndex);
2399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ cmp(r1, ip);
2400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ b(eq, &fast);
2401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ LoadRoot(ip, Heap::kFalseValueRootIndex);
2402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ cmp(r1, ip);
2403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ b(ne, &miss);
2404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
2405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
24067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
24070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss);
24083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
24093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
24103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            r0, holder, r3, r1, r4, name, &miss);
24113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // requires boxing.
24143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&miss);
2415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
24223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeFunction(
24233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind);
2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
24273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
243025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
24363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2438402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r2    : name
2439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- lr    : return address
2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
24416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
24429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
24439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
24444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Get the number of arguments.
24454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  const int argc = arguments().immediate();
24463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
24474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  LookupPostInterceptor(holder, name, &lookup);
24484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
24496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack.
24506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
2451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
24523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_);
24533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0,
24543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   &miss);
2455402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Move returned value, the function to call, to r1.
2457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(r1, r0);
24584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Restore receiver.
24596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
24604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
24613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
24653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24723ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal(
24733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
24743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
24753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
24763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
24773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r2    : name
2480402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- lr    : return address
2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
248244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
24833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
24843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
24853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
248659151504615d929945dc59db37bf1166937748c6Steve Block  }
248759151504615d929945dc59db37bf1166937748c6Steve Block
2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
24899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
24909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments.
2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
249359151504615d929945dc59db37bf1166937748c6Steve Block  GenerateGlobalReceiverCheck(object, holder, name, &miss);
249459151504615d929945dc59db37bf1166937748c6Steve Block  GenerateLoadFunctionFromCell(cell, function, &miss);
2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy if
2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary.
2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r3, MemOperand(sp, argc * kPointerSize));
2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the context (function already in r1).
2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the cached code (tail call).
250744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
250844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline(), 1, r3, r4);
2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(function->shared()->formal_parameter_count());
25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We call indirectly through the code field in the function to
25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // allow recompilation to take effect without changing any of the
25153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // call sites.
25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION,
25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                NullCallWrapper(), call_kind);
2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
252244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3);
25233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25303ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
25315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  int index,
25323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<Map> transition,
25333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<String> name) {
2534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
2536402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r1    : receiver
2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, r1, r2, r3, &miss);
2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
254444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
2545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
25483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25523ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback(
25533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
25543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback,
25553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
2558402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r1    : receiver
2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
25653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(r1, r3, Handle<Map>(object->map()), &miss,
25663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
2570402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ CheckAccessGlobalProxy(r1, r3, &miss);
2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2577402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(r1);  // receiver
25783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ip, Operand(callback));  // callback info
25796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(ip, r2, r0);
2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_callback_property =
258344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreCallbackProperty),
258444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        masm()->isolate());
25856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(store_callback_property, 4, 1);
2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
258944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor(
25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
25993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
2602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r1    : receiver
2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
26093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(r1, r3, Handle<Map>(receiver->map()), &miss,
26103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (receiver->IsJSGlobalProxy()) {
2614402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ CheckAccessGlobalProxy(r1, r3, &miss);
2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2617402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Stub is never generated for non-global objects that require access
2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(r1, r2, r0);  // Receiver, name, value.
2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ mov(r0, Operand(Smi::FromInt(strict_mode_)));
2624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(r0);  // strict mode
2625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_ic_property =
262844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty),
262944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        masm()->isolate());
2630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ TailCallExternalReference(store_ic_property, 4, 1);
2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
263444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal(
26433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> object,
26443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
26453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
2648402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r1    : receiver
2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
2655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
2656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r3, Operand(Handle<Map>(object->map())));
2657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the value in the cell is not the hole. If it is, this
26601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // cell could have been deleted and reintroducing the global needs
26611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // to update the property details in the property dictionary of the
26621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // global object. We bail out to the runtime system to do that.
26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r4, Operand(cell));
26641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
26651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(r6, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset));
26661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ cmp(r5, r6);
26671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ b(eq, &miss);
26681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Store the value in the cell.
26701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ str(r0, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset));
26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Cells are always rescanned, so no write barrier here.
2672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
267344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
267444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline(), 1, r4, r3);
2675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
2676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
267944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline_miss(), 1, r4, r3);
268044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
2681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26883ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
26893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> object,
26903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> last) {
26916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
2692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
26936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- lr    : return address
26946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
26956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
26966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that receiver is not a smi.
26983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r0, &miss);
26996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the maps of the full prototype chain.
27013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss);
27026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If the last object in the prototype chain is a global object,
27046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // check that the global property cell is empty.
27056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (last->IsGlobalObject()) {
27063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateCheckPropertyCell(
27073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm(), Handle<GlobalObject>::cast(last), name, r1, &miss);
27086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
27096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return undefined if maps of the full prototype chain are still the
27116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // same and no global property with this name contains a value.
27126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
27136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Ret();
27146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
27166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
27176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NONEXISTENT, factory()->empty_string());
27206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
27216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27233ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
27243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
27255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                int index,
27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
2727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(object, holder, r0, r3, r1, r4, index, name, &miss);
2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback(
27443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
27453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
27463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
27543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4, callback, name,
27553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       &miss);
2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
27663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> value,
27673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name) {
2768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadConstant(object, holder, r0, r3, r1, r4, value, name, &miss);
2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27843ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object,
27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
2787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
27954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  LookupPostInterceptor(holder, name, &lookup);
27963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(object, holder, &lookup, r0, r2, r3, r1, r4, name,
2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &miss);
2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal(
28073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
28103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
28113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_dont_delete) {
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
28203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(r0, &miss);
28213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss);
2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value from the cell.
28243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r3, Operand(cell));
28256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for deleted property if property can actually be deleted.
2828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!is_dont_delete) {
2829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
28306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ cmp(r4, ip);
2831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &miss);
2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r0, r4);
283544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
283644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3);
2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
284044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub_miss(), 1, r1, r3);
2841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28483ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
28493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> receiver,
28503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> holder,
28515913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                     int index) {
2852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
28546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
285525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
28603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss);
2864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
2868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28713ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback(
28723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
28733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
2876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
28786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
287925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
28843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, r4, callback, name,
28883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       &miss);
2889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28963ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant(
28973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
28983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
29003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> value) {
2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
29036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
290425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
29093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss);
2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29213ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
29233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
29243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
29276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
292825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
29333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
29374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  LookupPostInterceptor(holder, name, &lookup);
29383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(receiver, holder, &lookup, r1, r0, r2, r3, r4, name,
2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &miss);
2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29473ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
29483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
29516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
295225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
29573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateLoadArrayLength(masm(), r1, r2, &miss);
2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29683ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
29693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
29726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
297325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
297644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
297744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
297844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_string_length(), 1, r2, r3);
2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
29813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateLoadStringLength(masm(), r1, r2, r3, &miss, true);
2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
298644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_string_length(), 1, r2, r3);
2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29943ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
29953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
29986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
299925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
3000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
30018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label miss;
30028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
300344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
300444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3);
30058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
30068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check the name hasn't changed.
30073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r0, Operand(name));
30088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(ne, &miss);
30098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
30108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss);
30118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&miss);
301244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3);
3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
3016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement(
30203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
3021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
3022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- lr    : return address
3023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r0    : key
3024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r1    : receiver
3025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
3026589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
30273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode();
30283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK);
3030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
3033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
30353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
3036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30393ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic(
30403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
30413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_ics) {
3042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- lr    : return address
3044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r0    : key
3045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r1    : receiver
3046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
3048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(r1, &miss);
3049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int receiver_count = receiver_maps->length();
3051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
3052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int current = 0; current < receiver_count; ++current) {
30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ip, Operand(receiver_maps->at(current)));
3054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cmp(r2, ip);
30553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Jump(handler_ics->at(current), RelocInfo::CODE_TARGET, eq);
3056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
3059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss();
3060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
3061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Return the generated code.
30633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
3064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
30685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                       int index,
30693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<Map> transition,
30703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<String> name) {
3071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
3072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
3073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r1    : name
3074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r2    : receiver
3075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
3076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
3077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
3078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
307944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
308044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_store_field(), 1, r3, r4);
3081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
30833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r1, Operand(name));
3084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
3085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r3 is used as scratch register. r1 and r2 keep their values if a jump to
3087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the miss label is generated.
30883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, r2, r1, r3, &miss);
3089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
3090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
309144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4);
309244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
3093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
3094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
30963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
3097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31003ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement(
31013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
3102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
3103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r0    : value
3104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r1    : key
3105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r2    : receiver
3106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- lr    : return address
3107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- r3    : scratch
3108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
3109589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
3110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
31113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub =
31123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode();
31133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(r2, r3, receiver_map, stub, DO_SMI_CHECK);
3115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
3118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
31203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
3121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31243ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
31253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_stubs,
31273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* transitioned_maps) {
3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r0    : value
3130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r1    : key
3131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r2    : receiver
3132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- lr    : return address
3133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r3    : scratch
3134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
3136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(r2, &miss);
3137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int receiver_count = receiver_maps->length();
3139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
31403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < receiver_count; ++i) {
31413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ip, Operand(receiver_maps->at(i)));
3142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cmp(r3, ip);
31433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (transitioned_maps->at(i).is_null()) {
31443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq);
31453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
31463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label next_map;
31473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ b(ne, &next_map);
31483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r3, Operand(transitioned_maps->at(i)));
31493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, al);
31503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&next_map);
31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
3155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
3156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
3157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Return the generated code.
31593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
3160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
3161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
31633ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub(
31643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function) {
3165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
3166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : argc
3167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1    : constructor
3168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
3169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp]  : last argument
3170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
3171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_stub_call;
3172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use r7 for holding undefined which is used in several places below.
3174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check to see whether there are any break points in the function code. If
3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // there are jump to the generic constructor stub which calls the actual
3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code for the function thereby hitting the break points.
3180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset));
3182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, r7);
3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &generic_stub_call);
3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map and verify that it is in fact a map.
3187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
3188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
3189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
31903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r2, &generic_stub_call);
3191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(r2, r3, r4, MAP_TYPE);
3192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &generic_stub_call);
3193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
3195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cannot construct functions this way.
3196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
3197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
3198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: initial map
3199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
3200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
3201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Check(ne, "Function constructed by construct stub.");
3202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Now allocate the JSObject in new space.
3205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
3206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
3207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: initial map
3208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
3209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
32103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AllocateInNewSpace(r3, r4, r5, r6, &generic_stub_call, SIZE_IN_WORDS);
3211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSObject, now initialize the fields. Map is set to initial
3213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // map and properties and elements are set to empty fixed array.
3214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
3215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
3216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: initial map
3217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: object size (in words)
3218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject (not tagged)
3219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
3220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
3221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r5, r4);
3222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
3223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
3224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
3225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
3226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
3227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
3228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the first argument. The stack contains only the
3230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // argc arguments.
3231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2));
3232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill all the in-object properties with undefined.
3234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
3235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: first argument
3236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: object size (in words)
3237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject (not tagged)
3238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r5: First in-object property of JSObject (not tagged)
3239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
3240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the initialized properties with a constant value or a passed argument
3241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // depending on the this.x = ...; assignment in the function.
32423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<SharedFunctionInfo> shared(function->shared());
3243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
3244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (shared->IsThisPropertyAssignmentArgument(i)) {
3245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Label not_passed, next;
3246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check if the argument assigned to the property is actually passed.
3247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int arg_number = shared->GetThisPropertyAssignmentArgument(i);
3248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(r0, Operand(arg_number));
3249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(le, &not_passed);
3250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Argument passed - find it on the stack.
3251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ ldr(r2, MemOperand(r1, (arg_number + 1) * -kPointerSize));
3252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
3253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(&next);
3254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&not_passed);
3255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to undefined.
3256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
3257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&next);
3258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
3259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to the constant value.
3260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
3261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ mov(r2, Operand(constant));
3262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
3263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the unused in-object property fields with undefined.
32678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(function->has_initial_map());
3268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = shared->this_property_assignments_count();
32698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang       i < function->initial_map()->inobject_properties();
3270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       i++) {
3271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
3272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
3275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject (not tagged)
3276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move argc to r1 and the JSObject to return to r0 and tag it.
3277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r1, r0);
3278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r4);
3279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ orr(r0, r0, Operand(kHeapObjectTag));
3280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: JSObject
3282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: argc
3283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack and return.
3284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2));
3285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
328644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm()->isolate()->counters();
328744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects(), 1, r1, r2);
328844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects_stub(), 1, r1, r2);
3289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
3290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic stub in case the specialized code cannot handle the
3292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // construction.
3293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_stub_call);
329444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric();
329544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Jump(code, RelocInfo::CODE_TARGET);
3296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode();
3299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __
33033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm)
33043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
33063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
33073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
33083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ---------- S t a t e --------------
33093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- lr     : return address
33103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r0     : key
33113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r1     : receiver
3312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
33133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, miss_force_generic;
3314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register key = r0;
33163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register receiver = r1;
3317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(key, &miss_force_generic);
33193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(r2, Operand(key, ASR, kSmiTagSize));
33203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
33213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadFromNumberDictionary(&slow, r4, key, r0, r2, r3, r5);
33223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
3323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
33253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ IncrementCounter(
33263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->counters()->keyed_load_external_array_slow(),
33273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      1, r2, r3);
3328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ---------- S t a t e --------------
33303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- lr     : return address
33313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r0     : key
33323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r1     : receiver
3333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
33343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
33353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
33363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(slow_ic, RelocInfo::CODE_TARGET);
3337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Miss case, call the runtime.
33393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
3340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ---------- S t a t e --------------
33423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- lr     : return address
33433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r0     : key
33443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r1     : receiver
33453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
3346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_ic =
33483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
33493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
33503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
3351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3353589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochstatic bool IsElementTypeSigned(ElementsKind elements_kind) {
33543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
3356589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
3357589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
33581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      return true;
33591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3360589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3362589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3363589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
33641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      return false;
33651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
3367589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
3368589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_ELEMENTS:
33693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case FAST_SMI_ONLY_ELEMENTS:
3370589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_DOUBLE_ELEMENTS:
3371589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case DICTIONARY_ELEMENTS:
3372589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case NON_STRICT_ARGUMENTS_ELEMENTS:
33731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
33741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      return false;
33751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
33763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return false;
33771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
33781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray(
3381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3382589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
33831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------- S t a t e --------------
33841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- lr     : return address
33851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r0     : key
33861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r1     : receiver
33871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
3388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic, slow, failed_allocation;
33891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register key = r0;
33911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register receiver = r1;
33921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
33951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the key is a smi.
3397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(key, &miss_force_generic);
33981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
340044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // r3: elements array
34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the index is in range.
34031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
340469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmp(key, ip);
34051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
340669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ b(hs, &miss_force_generic);
34071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r3: base pointer of external storage
34101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We are not untagging smi key and instead work with it
34121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // as if it was premultiplied by 2.
341369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
34141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register value = r2;
34163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3417589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ ldrsb(value, MemOperand(r3, key, LSR, 1));
34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3420589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
3421589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
34221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ ldrb(value, MemOperand(r3, key, LSR, 1));
34231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3424589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
34251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ ldrsh(value, MemOperand(r3, key, LSL, 0));
34261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
34281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ ldrh(value, MemOperand(r3, key, LSL, 0));
34291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3430589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
3431589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
34321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ ldr(value, MemOperand(r3, key, LSL, 1));
34331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3434589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
34358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (CpuFeatures::IsSupported(VFP3)) {
34361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        CpuFeatures::Scope scope(VFP3);
34371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ add(r2, r3, Operand(key, LSL, 1));
34381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ vldr(s0, r2, 0);
34391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
34401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ ldr(value, MemOperand(r3, key, LSL, 1));
34411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
34421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3443589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (CpuFeatures::IsSupported(VFP3)) {
3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        CpuFeatures::Scope scope(VFP3);
3446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ add(r2, r3, Operand(key, LSL, 2));
3447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ vldr(d0, r2, 0);
3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ add(r4, r3, Operand(key, LSL, 2));
3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // r4: pointer to the beginning of the double we want to load.
3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ ldr(r2, MemOperand(r4, 0));
3452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ ldr(r3, MemOperand(r4, Register::kSizeInBytes));
3453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
3454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3455589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_ELEMENTS:
34563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case FAST_SMI_ONLY_ELEMENTS:
3457589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_DOUBLE_ELEMENTS:
3458589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case DICTIONARY_ELEMENTS:
3459589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case NON_STRICT_ARGUMENTS_ELEMENTS:
34601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
34611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
34621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
34631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For integer array types:
34651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r2: value
3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // For float array type:
34671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // s0: value (if VFP3 is supported)
34681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r2: value (if VFP3 is not supported)
3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // For double array type:
3470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // d0: value (if VFP3 is supported)
3471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // r2/r3: value (if VFP3 is not supported)
34721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3473589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_INT_ELEMENTS) {
34741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the Int and UnsignedInt array types, we need to see whether
34751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // the value can be represented in a Smi. If not, we need to convert
34761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // it to a HeapNumber.
34771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Label box_int;
34781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmp(value, Operand(0xC0000000));
34791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(mi, &box_int);
34801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Tag integer as smi and return it.
34811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(r0, Operand(value, LSL, kSmiTagSize));
34821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Ret();
34831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&box_int);
34851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Allocate a HeapNumber for the result and perform int-to-double
34861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // conversion.  Don't touch r0 or r1 as they are needed if allocation
34871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // fails.
34881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
34891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ AllocateHeapNumber(r5, r3, r4, r6, &slow);
34901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Now we can use r0 for the result as key is not needed any more.
34911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(r0, r5);
34921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (CpuFeatures::IsSupported(VFP3)) {
34941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      CpuFeatures::Scope scope(VFP3);
34951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vmov(s0, value);
34961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vcvt_f64_s32(d0, s0);
34971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ sub(r3, r0, Operand(kHeapObjectTag));
34981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vstr(d0, r3, HeapNumber::kValueOffset);
34991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
35001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
3501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Register dst1 = r1;
3502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Register dst2 = r3;
3503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FloatingPointHelper::Destination dest =
3504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          FloatingPointHelper::kCoreRegisters;
3505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FloatingPointHelper::ConvertIntToDouble(masm,
3506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              value,
3507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              dest,
3508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              d0,
3509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              dst1,
3510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              dst2,
3511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              r9,
3512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                              s0);
3513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ str(dst1, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
3514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ str(dst2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
3515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
35161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
3517589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
35181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // The test is different for unsigned int values. Since we need
35191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // the value to be in the range of a positive smi, we can't
35201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // handle either of the top two bits being set in the value.
35218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (CpuFeatures::IsSupported(VFP3)) {
35221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      CpuFeatures::Scope scope(VFP3);
35231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Label box_int, done;
35241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ tst(value, Operand(0xC0000000));
35251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ b(ne, &box_int);
35261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Tag integer as smi and return it.
35271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, Operand(value, LSL, kSmiTagSize));
35281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
35291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&box_int);
35311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vmov(s0, value);
35321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Allocate a HeapNumber for the result and perform int-to-double
35331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // conversion. Don't use r0 and r1 as AllocateHeapNumber clobbers all
35341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // registers - also when jumping due to exhausted young space.
35351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
35361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ AllocateHeapNumber(r2, r3, r4, r6, &slow);
35371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vcvt_f64_u32(d0, s0);
35391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ sub(r1, r2, Operand(kHeapObjectTag));
35401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vstr(d0, r1, HeapNumber::kValueOffset);
35411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, r2);
35431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
35441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
35451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Check whether unsigned integer fits into smi.
35461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Label box_int_0, box_int_1, done;
35471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ tst(value, Operand(0x80000000));
35481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ b(ne, &box_int_0);
35491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ tst(value, Operand(0x40000000));
35501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ b(ne, &box_int_1);
35511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Tag integer as smi and return it.
35521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, Operand(value, LSL, kSmiTagSize));
35531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
35541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Register hiword = value;  // r2.
35561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Register loword = r3;
35571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&box_int_0);
35591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Integer does not have leading zeros.
3560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      GenerateUInt2Double(masm, hiword, loword, r4, 0);
35611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ b(&done);
35621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&box_int_1);
35641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Integer has one leading zero.
3565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      GenerateUInt2Double(masm, hiword, loword, r4, 1);
35661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&done);
35691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Integer was converted to double in registers hiword:loword.
35701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber
35711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // clobbers all registers - also when jumping due to exhausted young
35721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // space.
35731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
35741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ AllocateHeapNumber(r4, r5, r7, r6, &slow);
35751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ str(hiword, FieldMemOperand(r4, HeapNumber::kExponentOffset));
35771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ str(loword, FieldMemOperand(r4, HeapNumber::kMantissaOffset));
35781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, r4);
35801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
35811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
3582589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
35831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the floating-point array type, we need to always allocate a
35841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // HeapNumber.
35858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (CpuFeatures::IsSupported(VFP3)) {
35861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      CpuFeatures::Scope scope(VFP3);
35871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Allocate a HeapNumber for the result. Don't use r0 and r1 as
35881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // AllocateHeapNumber clobbers all registers - also when jumping due to
35891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // exhausted young space.
35901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
35911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ AllocateHeapNumber(r2, r3, r4, r6, &slow);
35921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vcvt_f64_f32(d0, s0);
35931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ sub(r1, r2, Operand(kHeapObjectTag));
35941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ vstr(d0, r1, HeapNumber::kValueOffset);
35951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, r2);
35971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
35981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
35991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Allocate a HeapNumber for the result. Don't use r0 and r1 as
36001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // AllocateHeapNumber clobbers all registers - also when jumping due to
36011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // exhausted young space.
36021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
36031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ AllocateHeapNumber(r3, r4, r5, r6, &slow);
36041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // VFP is not available, do manual single to double conversion.
36051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // r2: floating point value (binary32)
36071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // r3: heap number for result
36081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Extract mantissa to r0. OK to clobber r0 now as there are no jumps to
36101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // the slow case from here.
36111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ and_(r0, value, Operand(kBinary32MantissaMask));
36121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Extract exponent to r1. OK to clobber r1 now as there are no jumps to
36141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // the slow case from here.
36151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r1, Operand(value, LSR, kBinary32MantissaBits));
36161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ and_(r1, r1, Operand(kBinary32ExponentMask >> kBinary32MantissaBits));
36171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Label exponent_rebiased;
36191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ teq(r1, Operand(0x00));
36201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ b(eq, &exponent_rebiased);
36211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ teq(r1, Operand(0xff));
36231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r1, Operand(0x7ff), LeaveCC, eq);
36241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ b(eq, &exponent_rebiased);
36251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Rebias exponent.
36271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ add(r1,
36281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block             r1,
36291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block             Operand(-kBinary32ExponentBias + HeapNumber::kExponentBias));
36301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ bind(&exponent_rebiased);
36321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ and_(r2, value, Operand(kBinary32SignMask));
36331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      value = no_reg;
36341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ orr(r2, r2, Operand(r1, LSL, HeapNumber::kMantissaBitsInTopWord));
36351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Shift mantissa.
36371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      static const int kMantissaShiftForHiWord =
36381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
36391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      static const int kMantissaShiftForLoWord =
36411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          kBitsPerInt - kMantissaShiftForHiWord;
36421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ orr(r2, r2, Operand(r0, LSR, kMantissaShiftForHiWord));
36441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, Operand(r0, LSL, kMantissaShiftForLoWord));
36451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ str(r2, FieldMemOperand(r3, HeapNumber::kExponentOffset));
36471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ str(r0, FieldMemOperand(r3, HeapNumber::kMantissaOffset));
36481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ mov(r0, r3);
36501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
36511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
3652589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (CpuFeatures::IsSupported(VFP3)) {
3654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CpuFeatures::Scope scope(VFP3);
3655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Allocate a HeapNumber for the result. Don't use r0 and r1 as
3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // AllocateHeapNumber clobbers all registers - also when jumping due to
3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // exhausted young space.
3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
3659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ AllocateHeapNumber(r2, r3, r4, r6, &slow);
3660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ sub(r1, r2, Operand(kHeapObjectTag));
3661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ vstr(d0, r1, HeapNumber::kValueOffset);
3662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ mov(r0, r2);
3664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else {
3666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // Allocate a HeapNumber for the result. Don't use r0 and r1 as
3667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // AllocateHeapNumber clobbers all registers - also when jumping due to
3668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // exhausted young space.
3669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ LoadRoot(r7, Heap::kHeapNumberMapRootIndex);
3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ AllocateHeapNumber(r4, r5, r6, r7, &slow);
3671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ str(r2, FieldMemOperand(r4, HeapNumber::kMantissaOffset));
3673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ str(r3, FieldMemOperand(r4, HeapNumber::kExponentOffset));
3674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ mov(r0, r4);
3675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ Ret();
3676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
36771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
36791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Tag integer as smi and return it.
36801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(r0, Operand(value, LSL, kSmiTagSize));
36811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Ret();
36821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
36831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Slow case, key and receiver still in r0 and r1.
36851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
368644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(
3687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->counters()->keyed_load_external_array_slow(),
368844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      1, r2, r3);
36891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------- S t a t e --------------
36911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- lr     : return address
36921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r0     : key
36931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r1     : receiver
36941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
36951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ Push(r1, r0);
36971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
36991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
37013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub =
37023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
37033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(stub, RelocInfo::CODE_TARGET);
37041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
37051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray(
3708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3709589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
37101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------- S t a t e --------------
37111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r0     : value
37121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r1     : key
37131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- r2     : receiver
37141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- lr     : return address
37151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
3716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label slow, check_heap_number, miss_force_generic;
37171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Register usage.
37191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register value = r0;
37201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register key = r1;
37211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register receiver = r2;
37221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r3 mostly holds the elements array or the destination external array.
37231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
37261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the key is a smi.
3728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(key, &miss_force_generic);
37291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
373069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
373169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
373244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the index is in range
37331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
373469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmp(key, ip);
37351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
3736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ b(hs, &miss_force_generic);
37371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Handle both smis and HeapNumbers in the fast path. Go to the
37391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // runtime for all other kinds of values.
37401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r3: external array.
3741589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
374244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Double to pixel conversion is only implemented in the runtime for now.
374344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ JumpIfNotSmi(value, &slow);
374444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
374544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ JumpIfNotSmi(value, &check_heap_number);
374644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
374744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiUntag(r5, value);
37481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
37491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r3: base pointer of external storage.
37511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // r5: value (integer).
37523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3753589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
375444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Clamp the value to [0..255].
375544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ Usat(r5, 8, Operand(r5));
375669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ strb(r5, MemOperand(r3, key, LSR, 1));
375744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
3758589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
3759589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
376069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ strb(r5, MemOperand(r3, key, LSR, 1));
37611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3762589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
3763589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
376469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ strh(r5, MemOperand(r3, key, LSL, 0));
37651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3766589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
3767589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
376869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ str(r5, MemOperand(r3, key, LSL, 1));
37691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3770589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
37711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Perform int-to-float conversion and store to memory.
377269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(r4, key);
3773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9);
3774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
3775589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
377669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ add(r3, r3, Operand(key, LSL, 2));
3777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // r3: effective address of the double element
3778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FloatingPointHelper::Destination destination;
3779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (CpuFeatures::IsSupported(VFP3)) {
3780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        destination = FloatingPointHelper::kVFPRegisters;
3781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
3782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        destination = FloatingPointHelper::kCoreRegisters;
3783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
3784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      FloatingPointHelper::ConvertIntToDouble(
3785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          masm, r5, destination,
3786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          d0, r6, r7,  // These are: double_dst, dst1, dst2.
3787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          r4, s2);  // These are: scratch2, single_scratch.
3788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (destination == FloatingPointHelper::kVFPRegisters) {
3789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        CpuFeatures::Scope scope(VFP3);
3790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ vstr(d0, r3, 0);
3791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else {
3792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ str(r6, MemOperand(r3, 0));
3793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ str(r7, MemOperand(r3, Register::kSizeInBytes));
3794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
37951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3796589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_ELEMENTS:
37973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case FAST_SMI_ONLY_ELEMENTS:
3798589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case FAST_DOUBLE_ELEMENTS:
3799589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case DICTIONARY_ELEMENTS:
3800589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case NON_STRICT_ARGUMENTS_ELEMENTS:
38011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
38021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
38031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
38041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
38051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Entry registers are intact, r0 holds the value which is the return value.
38061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ Ret();
38071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3808589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
380944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // r3: external array.
381044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ bind(&check_heap_number);
381144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE);
381244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ b(ne, &slow);
38131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
381444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
38151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
381644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // r3: base pointer of external storage.
38171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
381844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The WebGL specification leaves the behavior of storing NaN and
381944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // +/-Infinity into integer arrays basically undefined. For more
382044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // reproducible behavior, convert these to zero.
38218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (CpuFeatures::IsSupported(VFP3)) {
382244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      CpuFeatures::Scope scope(VFP3);
38231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3824589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
382544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // vldr requires offset to be a multiple of 4 so we can not
382644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // include -kHeapObjectTag into it.
382744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ sub(r5, r0, Operand(kHeapObjectTag));
382844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ vldr(d0, r5, HeapNumber::kValueOffset);
382969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ add(r5, r3, Operand(key, LSL, 1));
383044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ vcvt_f32_f64(s0, d0);
383144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ vstr(s0, r5, 0);
3832589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ sub(r5, r0, Operand(kHeapObjectTag));
3834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ vldr(d0, r5, HeapNumber::kValueOffset);
383569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ add(r5, r3, Operand(key, LSL, 2));
3836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ vstr(d0, r5, 0);
38371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
383844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // Hoisted load.  vldr requires offset to be a multiple of 4 so we can
383944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // not include -kHeapObjectTag into it.
384044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ sub(r5, value, Operand(kHeapObjectTag));
384144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ vldr(d0, r5, HeapNumber::kValueOffset);
38423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        __ EmitECMATruncate(r5, d0, s2, r6, r7, r9);
384344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
38443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        switch (elements_kind) {
3845589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_BYTE_ELEMENTS:
3846589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
384769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ strb(r5, MemOperand(r3, key, LSR, 1));
384844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
3849589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_SHORT_ELEMENTS:
3850589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
385169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ strh(r5, MemOperand(r3, key, LSL, 0));
385244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
3853589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_INT_ELEMENTS:
3854589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_INT_ELEMENTS:
385569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ str(r5, MemOperand(r3, key, LSL, 1));
385644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
3857589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_PIXEL_ELEMENTS:
3858589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_FLOAT_ELEMENTS:
3859589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_DOUBLE_ELEMENTS:
3860589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case FAST_ELEMENTS:
38613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          case FAST_SMI_ONLY_ELEMENTS:
3862589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case FAST_DOUBLE_ELEMENTS:
3863589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case DICTIONARY_ELEMENTS:
3864589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case NON_STRICT_ARGUMENTS_ELEMENTS:
386544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            UNREACHABLE();
386644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
386744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
38681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
38691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
38701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Entry registers are intact, r0 holds the value which is the return
38711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // value.
38721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ Ret();
38731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
387444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // VFP3 is not available do manual conversions.
387544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset));
387644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset));
387744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3878589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
387944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Label done, nan_or_infinity_or_zero;
388044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        static const int kMantissaInHiWordShift =
388144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
388244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
388344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        static const int kMantissaInLoWordShift =
388444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            kBitsPerInt - kMantissaInHiWordShift;
388544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
388644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // Test for all special exponent values: zeros, subnormal numbers, NaNs
388744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // and infinities. All these should be converted to 0.
388844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r7, Operand(HeapNumber::kExponentMask));
388944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r9, r5, Operand(r7), SetCC);
389044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(eq, &nan_or_infinity_or_zero);
389144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
389244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ teq(r9, Operand(r7));
389344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r9, Operand(kBinary32ExponentMask), LeaveCC, eq);
389444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(eq, &nan_or_infinity_or_zero);
389544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
389644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // Rebias exponent.
389744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
389844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ add(r9,
389944f0eee88ff00398ff7f715fab053374d808c90dSteve Block               r9,
390044f0eee88ff00398ff7f715fab053374d808c90dSteve Block               Operand(kBinary32ExponentBias - HeapNumber::kExponentBias));
390144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
390244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ cmp(r9, Operand(kBinary32MaxExponent));
390344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, gt);
390444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r5, r5, Operand(kBinary32ExponentMask), LeaveCC, gt);
390544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(gt, &done);
390644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
390744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ cmp(r9, Operand(kBinary32MinExponent));
390844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, lt);
390944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(lt, &done);
391044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
391144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r7, r5, Operand(HeapNumber::kSignMask));
391244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
391344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r7, r7, Operand(r5, LSL, kMantissaInHiWordShift));
391444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r7, r7, Operand(r6, LSR, kMantissaInLoWordShift));
391544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r5, r7, Operand(r9, LSL, kBinary32ExponentShift));
391644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
391744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ bind(&done);
391869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ str(r5, MemOperand(r3, key, LSL, 1));
391944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // Entry registers are intact, r0 holds the value which is the return
392044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // value.
392144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ Ret();
392244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
392344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ bind(&nan_or_infinity_or_zero);
392444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r7, r5, Operand(HeapNumber::kSignMask));
392544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
392644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r9, r9, r7);
392744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift));
392844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift));
392944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(&done);
3930589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
393169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ add(r7, r3, Operand(key, LSL, 2));
3932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // r7: effective address of destination element.
3933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ str(r6, MemOperand(r7, 0));
3934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ str(r5, MemOperand(r7, Register::kSizeInBytes));
3935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ Ret();
393644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else {
39373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        bool is_signed_type = IsElementTypeSigned(elements_kind);
393844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt;
393944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000;
394044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
394144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Label done, sign;
394244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
394344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // Test for all special exponent values: zeros, subnormal numbers, NaNs
394444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // and infinities. All these should be converted to 0.
394544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r7, Operand(HeapNumber::kExponentMask));
394644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r9, r5, Operand(r7), SetCC);
394744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
394844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(eq, &done);
394944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
395044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ teq(r9, Operand(r7));
395144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
395244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(eq, &done);
395344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
395444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // Unbias exponent.
395544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
395644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC);
395744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // If exponent is negative then result is 0.
395844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, mi);
395944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(mi, &done);
396044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
396144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // If exponent is too big then result is minimal value.
396244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ cmp(r9, Operand(meaningfull_bits - 1));
396344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r5, Operand(min_value), LeaveCC, ge);
396444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(ge, &done);
396544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
396644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r7, r5, Operand(HeapNumber::kSignMask), SetCC);
396744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
396844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r5, r5, Operand(1u << HeapNumber::kMantissaBitsInTopWord));
396944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
397044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ rsb(r9, r9, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC);
397144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl);
397244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ b(pl, &sign);
397344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
397444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ rsb(r9, r9, Operand(0, RelocInfo::NONE));
397544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ mov(r5, Operand(r5, LSL, r9));
397644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ rsb(r9, r9, Operand(meaningfull_bits));
397744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ orr(r5, r5, Operand(r6, LSR, r9));
397844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
397944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ bind(&sign);
398044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ teq(r7, Operand(0, RelocInfo::NONE));
398144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne);
398244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
398344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ bind(&done);
39843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        switch (elements_kind) {
3985589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_BYTE_ELEMENTS:
3986589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
398769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ strb(r5, MemOperand(r3, key, LSR, 1));
398844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
3989589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_SHORT_ELEMENTS:
3990589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
399169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ strh(r5, MemOperand(r3, key, LSL, 0));
399244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
3993589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_INT_ELEMENTS:
3994589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_UNSIGNED_INT_ELEMENTS:
399569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ str(r5, MemOperand(r3, key, LSL, 1));
399644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
3997589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_PIXEL_ELEMENTS:
3998589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_FLOAT_ELEMENTS:
3999589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case EXTERNAL_DOUBLE_ELEMENTS:
4000589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case FAST_ELEMENTS:
40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          case FAST_SMI_ONLY_ELEMENTS:
4002589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case FAST_DOUBLE_ELEMENTS:
4003589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case DICTIONARY_ELEMENTS:
4004589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          case NON_STRICT_ARGUMENTS_ELEMENTS:
400544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            UNREACHABLE();
400644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            break;
400744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
40081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
40091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
40101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
40111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Slow case, key and receiver still in r0 and r1.
40131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
4014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(
4015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->counters()->keyed_load_external_array_slow(),
4016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      1, r2, r3);
40171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
40181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ---------- S t a t e --------------
40191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- lr     : return address
4020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r0     : key
4021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r1     : receiver
40221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
4023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> slow_ic =
4024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_Slow();
4025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(slow_ic, RelocInfo::CODE_TARGET);
40261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Miss case, call the runtime.
4028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
40291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ---------- S t a t e --------------
4031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- lr     : return address
4032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r0     : key
4033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r1     : receiver
4034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
4035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
4037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
4039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
4043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
4044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- lr    : return address
4045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r0    : key
4046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r1    : receiver
4047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
4048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic;
4049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
4051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
40521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
4054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotSmi(r0, &miss_force_generic);
4055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array.
4057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
4058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AssertFastElements(r2);
4059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is within bounds.
4061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r3, FieldMemOperand(r2, FixedArray::kLengthOffset));
4062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmp(r0, Operand(r3));
4063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ b(hs, &miss_force_generic);
4064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the result and make sure it's not the hole.
4066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ add(r3, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
406769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
4068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r4,
4069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
4070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
4071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmp(r4, ip);
4072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ b(eq, &miss_force_generic);
4073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(r0, r4);
4074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
4075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
40773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub =
40783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
40793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(stub, RelocInfo::CODE_TARGET);
4080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
4081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
40833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
40843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
40853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
40863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- lr    : return address
40873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r0    : key
40883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r1    : receiver
40893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
40903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label miss_force_generic, slow_allocate_heapnumber;
40913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
40923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register key_reg = r0;
40933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register receiver_reg = r1;
40943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register elements_reg = r2;
40953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register heap_number_reg = r2;
40963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register indexed_double_offset = r3;
40973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register scratch = r4;
40983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register scratch2 = r5;
40993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register scratch3 = r6;
41003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register heap_number_map = r7;
41013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
41033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
41043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a smi.
41063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(key_reg, &miss_force_generic);
41073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the elements array.
41093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ldr(elements_reg,
41103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
41113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is within bounds.
41133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
41143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(key_reg, Operand(scratch));
41153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ b(hs, &miss_force_generic);
41163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Load the upper word of the double in the fixed array and test for NaN.
41183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ add(indexed_double_offset, elements_reg,
41193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
41203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t upper_32_offset = FixedArray::kHeaderSize + sizeof(kHoleNanLower32);
41213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ldr(scratch, FieldMemOperand(indexed_double_offset, upper_32_offset));
41223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(scratch, Operand(kHoleNanUpper32));
41233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ b(&miss_force_generic, eq);
41243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Non-NaN. Allocate a new heap number and copy the double value into it.
41263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
41273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AllocateHeapNumber(heap_number_reg, scratch2, scratch3,
41283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        heap_number_map, &slow_allocate_heapnumber);
41293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Don't need to reload the upper 32 bits of the double, it's already in
41313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // scratch.
41323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ str(scratch, FieldMemOperand(heap_number_reg,
41333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  HeapNumber::kExponentOffset));
41343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ldr(scratch, FieldMemOperand(indexed_double_offset,
41353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  FixedArray::kHeaderSize));
41363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ str(scratch, FieldMemOperand(heap_number_reg,
41373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  HeapNumber::kMantissaOffset));
41383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(r0, heap_number_reg);
41403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
41413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow_allocate_heapnumber);
41433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
41443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
41453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(slow_ic, RelocInfo::CODE_TARGET);
41463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
41483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_ic =
41493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
41503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
41513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
41523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
41543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement(
41553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
41563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
41573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind elements_kind,
41583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
4159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
4160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r0    : value
4161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r1    : key
4162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r2    : receiver
4163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- lr    : return address
4164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r3    : scratch
4165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r4    : scratch (elements)
4166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
41673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, transition_elements_kind, grow, slow;
41683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label finish_store, check_capacity;
4169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register value_reg = r0;
4171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register key_reg = r1;
4172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register receiver_reg = r2;
41733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = r4;
41743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register elements_reg = r3;
41753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register length_reg = r5;
41763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch2 = r6;
4177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
4179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
4180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
41823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(key_reg, &miss_force_generic);
4183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
41843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
41853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotSmi(value_reg, &transition_elements_kind);
41863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
418785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
418885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Check that the key is within bounds.
41893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(elements_reg,
41903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (is_js_array) {
4192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
4194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
4196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Compare smis.
4197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmp(key_reg, scratch);
41983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
41993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(hs, &grow);
42003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
42013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(hs, &miss_force_generic);
42023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
42043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Make sure elements is a fast element array, not 'cow'.
42053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(elements_reg,
42063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              scratch,
42073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Heap::kFixedArrayMapRootIndex,
42083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              &miss_force_generic,
42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DONT_DO_SMI_CHECK);
42105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
42133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(scratch,
42143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           elements_reg,
42153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Operand(FixedArray::kHeaderSize - kHeapObjectTag));
42163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
42173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(scratch,
42183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           scratch,
42193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
42203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(value_reg, MemOperand(scratch));
42213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
42223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(elements_kind == FAST_ELEMENTS);
42233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(scratch,
42243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           elements_reg,
42253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Operand(FixedArray::kHeaderSize - kHeapObjectTag));
42263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
42273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(scratch,
42283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           scratch,
42293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(value_reg, MemOperand(scratch));
42313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(receiver_reg, value_reg);
42323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWrite(elements_reg,  // Object.
42333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   scratch,       // Address.
42343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   receiver_reg,  // Value.
42353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   kLRHasNotBeenSaved,
42363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   kDontSaveFPRegs);
42373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // value_reg (r0) is preserved.
4239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Done.
4240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
4241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
4242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
4243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic =
4244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
42463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
42483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(ic_miss, RelocInfo::CODE_TARGET);
42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array by a single element if possible.
42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime. Flags already set by previous compare.
42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &miss_force_generic);
42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(length_reg,
42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(elements_reg,
42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(elements_reg, Heap::kEmptyFixedArrayRootIndex);
42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &check_capacity);
42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, elements_reg, scratch, scratch2, &slow,
42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          TAG_OBJECT);
42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
42733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(scratch, FieldMemOperand(elements_reg, JSObject::kMapOffset));
42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(scratch, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(scratch, FieldMemOperand(elements_reg, FixedArray::SizeFor(i)));
42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Store the element at index zero.
42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(value_reg, FieldMemOperand(elements_reg, FixedArray::SizeFor(0)));
42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(elements_reg,
42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg,
42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch, kLRHasNotBeenSaved, kDontSaveFPRegs,
42893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(length_reg, Operand(Smi::FromInt(1)));
42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
42943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Ret();
42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for cow elements, in general they are not handled by this stub
42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CheckMap(elements_reg,
42993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                scratch,
43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                Heap::kFixedCOWArrayMapRootIndex,
43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                &miss_force_generic,
43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                DONT_DO_SMI_CHECK);
43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(length_reg, scratch);
43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(hs, &slow);
43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(length_reg, length_reg, Operand(Smi::FromInt(1)));
43103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
43113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
43123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
43143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
43153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Jump(ic_slow, RelocInfo::CODE_TARGET);
43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
43181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
43191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
43203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
43213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm,
43223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
43233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
43243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
43253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r0    : value
43263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r1    : key
43273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r2    : receiver
43283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- lr    : return address
43293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r3    : scratch
43303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r4    : scratch
43313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- r5    : scratch
43323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
43333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, transition_elements_kind, grow, slow;
43343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label finish_store, check_capacity;
43353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register value_reg = r0;
43373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register key_reg = r1;
43383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register receiver_reg = r2;
43393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register elements_reg = r3;
43403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch1 = r4;
43413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch2 = r5;
43423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch3 = r6;
43433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register scratch4 = r7;
43443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register length_reg = r7;
43453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
43473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
43483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(key_reg, &miss_force_generic);
43493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ldr(elements_reg,
43513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
43523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is within bounds.
43543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (is_js_array) {
43553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
43563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
43573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(scratch1,
43583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
43593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
43603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compare smis, unsigned compare catches both negative and out-of-bound
43613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // indexes.
43623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(key_reg, scratch1);
43633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (grow_mode == ALLOW_JSARRAY_GROWTH) {
43643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(hs, &grow);
43655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  } else {
43663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(hs, &miss_force_generic);
43675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
43683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
43703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreNumberToDoubleElements(value_reg,
43713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 key_reg,
43723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 receiver_reg,
43733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 elements_reg,
43743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch1,
43753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch2,
43763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch3,
43773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch4,
43783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 &transition_elements_kind);
43793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
43803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Handle store cache miss, replacing the ic with the generic stub.
43823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
43833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> ic =
43843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
43853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(ic, RelocInfo::CODE_TARGET);
43863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
43883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
43893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(ic_miss, RelocInfo::CODE_TARGET);
43903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
43923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array by a single element if possible.
43933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
43943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
43963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime. Flags already set by previous compare.
43973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &miss_force_generic);
43983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Transition on values that can't be stored in a FixedDoubleArray.
44003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label value_is_smi;
44013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(value_reg, &value_is_smi);
44023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
44033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(scratch1, Heap::kHeapNumberMapRootIndex);
44043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &transition_elements_kind);
44053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&value_is_smi);
44063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
44083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
44093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(length_reg,
44103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
44113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(elements_reg,
44123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
44133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(elements_reg, Heap::kEmptyFixedArrayRootIndex);
44143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &check_capacity);
44153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, elements_reg, scratch1, scratch2, &slow,
44183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          TAG_OBJECT);
44193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Initialize the new FixedDoubleArray. Leave elements unitialized for
44213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // efficiency, they are guaranteed to be initialized before use.
44223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(scratch1, Heap::kFixedDoubleArrayMapRootIndex);
44233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(scratch1, FieldMemOperand(elements_reg, JSObject::kMapOffset));
44243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(scratch1,
44253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
44263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(scratch1,
44273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset));
44283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
44303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(elements_reg,
44313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
44323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg,
44333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch1, kLRHasNotBeenSaved, kDontSaveFPRegs,
44343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
44353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
44373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(length_reg, Operand(Smi::FromInt(1)));
44383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
44399413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch    __ ldr(elements_reg,
44409413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch           FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
44413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
44423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
44443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
44453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(scratch1,
44463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset));
44473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(length_reg, scratch1);
44483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(hs, &slow);
44493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
44513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(length_reg, length_reg, Operand(Smi::FromInt(1)));
44523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
44533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
44543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
44563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
44573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Jump(ic_slow, RelocInfo::CODE_TARGET);
44583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
44593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
44603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
44613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
4463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
4465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
4467