stub-cache-arm.cc revision 8a31eba00023874d4a1dcdc5f411cc4336776874
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2009 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"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.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
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ProbeTable(MacroAssembler* masm,
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Code::Flags flags,
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       StubCache::Table table,
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Register name,
463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                       Register offset,
473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                       Register scratch,
483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                       Register scratch2) {
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference key_offset(SCTableReference::keyReference(table));
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference value_offset(SCTableReference::valueReference(table));
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address());
533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address());
543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Check the relative positions of the address fields.
563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(value_off_addr > key_off_addr);
573e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT((value_off_addr - key_off_addr) % 4 == 0);
583e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT((value_off_addr - key_off_addr) < (256 * 4));
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  Label miss;
613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  Register offsets_base_addr = scratch;
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the key in the entry matches the name.
643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  __ mov(offsets_base_addr, Operand(key_offset));
653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  __ ldr(ip, MemOperand(offsets_base_addr, offset, LSL, 1));
666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(name, ip);
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the code entry from the cache.
703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  __ add(offsets_base_addr, offsets_base_addr,
713e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu         Operand(value_off_addr - key_off_addr));
723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  __ ldr(scratch2, MemOperand(offsets_base_addr, offset, LSL, 1));
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the flags match what we're looking for.
753e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  __ ldr(scratch2, FieldMemOperand(scratch2, Code::kFlagsOffset));
763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  __ bic(scratch2, scratch2, Operand(Code::kFlagsNotUsedInLookup));
773e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  __ cmp(scratch2, Operand(flags));
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
803e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Re-load code entry from cache.
813e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  __ ldr(offset, MemOperand(offsets_base_addr, offset, LSL, 1));
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the first instruction in the code stub.
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag));
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(offset);
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Miss: fall through.
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Helper function used to check that the dictionary doesn't contain
933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// the property. This function may return false negatives, so miss_label
943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// must always call a backup property check that is complete.
953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// This function is safe to call if the receiver has fast properties.
963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Name must be a symbol and receiver must be a heap object.
973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                             Label* miss_label,
993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                             Register receiver,
1003bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                             String* name,
1013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                             Register scratch0,
1023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                             Register scratch1) {
1033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(name->IsSymbol());
1043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ IncrementCounter(&Counters::negative_lookups, 1, scratch0, scratch1);
1053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ IncrementCounter(&Counters::negative_lookups_miss, 1, scratch0, scratch1);
1063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Label done;
1083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const int kInterceptorOrAccessCheckNeededMask =
1103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
1113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Bail out if the receiver has a named interceptor or requires access checks.
1133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register map = scratch1;
1143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
1153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
1163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
1173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ b(ne, miss_label);
1183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check that receiver is a JSObject.
1203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
1213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ cmp(scratch0, Operand(FIRST_JS_OBJECT_TYPE));
1223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ b(lt, miss_label);
1233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Load properties array.
1253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register properties = scratch0;
1263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
1273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check that the properties array is a dictionary.
1283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset));
1293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register tmp = properties;
1303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
1313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ cmp(map, tmp);
1323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ b(ne, miss_label);
1333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Restore the temporarily used register.
1353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
1363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Compute the capacity mask.
1383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const int kCapacityOffset =
1393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      StringDictionary::kHeaderSize +
1403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      StringDictionary::kCapacityIndex * kPointerSize;
1413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Generate an unrolled loop that performs a few probes before
1433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // giving up.
1443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  static const int kProbes = 4;
1453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const int kElementsStartOffset =
1463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      StringDictionary::kHeaderSize +
1473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      StringDictionary::kElementsStartIndex * kPointerSize;
1483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // If names of slots in range from 1 to kProbes - 1 for the hash value are
1503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // not equal to the name and kProbes-th slot is not used (its name is the
1513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // undefined value), it guarantees the hash table doesn't contain the
1523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // property. It's true even if some slots represent deleted properties
1533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // (their names are the null value).
1543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  for (int i = 0; i < kProbes; i++) {
1553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // scratch0 points to properties hash.
1563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Compute the masked index: (hash + i + i * i) & mask.
1573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    Register index = scratch1;
1583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Capacity is smi 2^n.
1593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ ldr(index, FieldMemOperand(properties, kCapacityOffset));
1603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ sub(index, index, Operand(1));
1613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ and_(index, index, Operand(
1623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i))));
1633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Scale the index by multiplying by the entry size.
1653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    ASSERT(StringDictionary::kEntrySize == 3);
1663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ add(index, index, Operand(index, LSL, 1));  // index *= 3.
1673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    Register entity_name = scratch1;
1693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Having undefined at this place means the name is not contained.
1703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    ASSERT_EQ(kSmiTagSize, 1);
1713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    Register tmp = properties;
1723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ add(tmp, properties, Operand(index, LSL, 1));
1733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
1743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    ASSERT(!tmp.is(entity_name));
1763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
1773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ cmp(entity_name, tmp);
1783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    if (i != kProbes - 1) {
1793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ b(eq, &done);
1803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Stop if found the property.
1823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ cmp(entity_name, Operand(Handle<String>(name)));
1833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ b(eq, miss_label);
1843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Check if the entry name is not a symbol.
1863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
1873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ ldrb(entity_name,
1883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch              FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
1893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ tst(entity_name, Operand(kIsSymbolMask));
1903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ b(eq, miss_label);
1913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Restore the properties.
1933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ ldr(properties,
1943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch             FieldMemOperand(receiver, JSObject::kPropertiesOffset));
1953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    } else {
1963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Give up probing if still not found the undefined value.
1973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ b(ne, miss_label);
1983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    }
1993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
2003bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ bind(&done);
2013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ DecrementCounter(&Counters::negative_lookups_miss, 1, scratch0, scratch1);
2023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
2033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm,
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Code::Flags flags,
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register receiver,
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register name,
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register scratch,
2103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                              Register extra,
2113e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                              Register extra2) {
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that code is valid. The shifting code relies on the
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // entry size being 8.
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(sizeof(Entry) == 8);
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the flags does not name a specific type.
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that there are no register conflicts.
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(receiver));
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(name));
2243e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra.is(receiver));
2253e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra.is(name));
2263e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra.is(scratch));
2273e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra2.is(receiver));
2283e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra2.is(name));
2293e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra2.is(scratch));
2303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra2.is(extra));
2313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
2323e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Check scratch, extra and extra2 registers are valid.
2333e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!scratch.is(no_reg));
2343e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra.is(no_reg));
2353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!extra2.is(no_reg));
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver, Operand(kSmiTagMask));
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &miss);
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the map of the receiver and compute the hash.
242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset));
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(scratch, scratch, Operand(ip));
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ eor(scratch, scratch, Operand(flags));
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch,
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          scratch,
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize));
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the primary table.
2513e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ProbeTable(masm, flags, kPrimary, name, scratch, extra, extra2);
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Primary miss: Compute hash for secondary probe.
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(scratch, scratch, Operand(name));
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(scratch, scratch, Operand(flags));
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch,
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          scratch,
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize));
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the secondary table.
2613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ProbeTable(masm, flags, kSecondary, name, scratch, extra, extra2);
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache miss: Fall-through and let caller handle the miss by
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // entering the runtime system.
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       int index,
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       Register prototype) {
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global or builtins object from the current context.
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context from the global or builtins object.
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype,
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset));
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the function from the global context.
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index)));
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map.  The global functions all have initial maps.
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype,
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the prototype from the initial map.
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
2880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    MacroAssembler* masm, int index, Register prototype, Label* miss) {
2890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check we're still in the same context.
2900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
2910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(ip, Top::global());
2920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ cmp(prototype, ip);
2930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ b(ne, miss);
2947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get the global function with the given index.
2957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  JSFunction* function = JSFunction::cast(Top::global_context()->get(index));
2967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load its initial map. The global functions all have initial maps.
2977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Move(prototype, Handle<Map>(function->initial_map()));
2987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load the prototype from the initial map.
2997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
3007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
3017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load a fast property out of a holder object (src). In-object properties
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are loaded directly otherwise the property is loaded from the properties
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// fixed array.
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register dst, Register src,
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            JSObject* holder, int index) {
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust for the number of properties stored in the holder.
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index -= holder->map()->inobject_properties();
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the property straight out of the holder.
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = holder->map()->instance_size() + (index * kPointerSize);
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(dst, FieldMemOperand(src, offset));
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate the offset into the properties array.
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(dst, FieldMemOperand(dst, offset));
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch,
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss_label) {
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver, Operand(kSmiTagMask));
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, miss_label);
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a JS array.
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, miss_label);
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load length directly from the JS array.
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
342402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Generate code to check if an object is a string.  If the object is a
343402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// heap object, its map's instance type is left in the scratch1 register.
344402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// If this is not needed, scratch1 and scratch2 may be the same register.
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm,
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register receiver,
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register scratch1,
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register scratch2,
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* smi,
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* non_string_object) {
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver, Operand(kSmiTagMask));
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, smi);
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a string.
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The cast is to resolve the overload for the argument of 0x0.
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, non_string_object);
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to load the length from a string object and return the length.
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the receiver object is not a string or a wrapped string object the
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// execution continues at the miss label. The register containing the
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// receiver is potentially clobbered.
369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
370402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register receiver,
371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register scratch1,
372402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register scratch2,
373402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Label* miss) {
374402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label check_wrapper;
375402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the object is a string leaving the instance type in the
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch1 register.
378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateStringCheck(masm, receiver, scratch1, scratch2, miss, &check_wrapper);
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load length directly from the string.
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the object is a JSValue wrapper.
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&check_wrapper);
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(scratch1, Operand(JS_VALUE_TYPE));
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, miss);
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Unwrap the value and check if the wrapped value is a string.
390402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset));
391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss);
392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(r0, FieldMemOperand(scratch1, String::kLengthOffset));
393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ Ret();
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register receiver,
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register scratch1,
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register scratch2,
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Label* miss_label) {
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, scratch1);
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate StoreField code, value is passed in r0 register.
409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// When leaving generated code after success, the receiver_reg and name_reg
410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// may be clobbered.  Upon branch to miss_label, the receiver and name
411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// registers have their original values.
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm,
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      JSObject* object,
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      int index,
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Map* transition,
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register receiver_reg,
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register name_reg,
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch,
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* miss_label) {
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0 : value
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label exit;
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver_reg, Operand(kSmiTagMask));
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, miss_label);
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the receiver hasn't changed.
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(scratch, Operand(Handle<Map>(object->map())));
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, miss_label);
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform map transition for the receiver if necessary.
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The properties must be extended before we can store the value.
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We jump to a runtime call that extends the properties array.
445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(receiver_reg);
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, Operand(Handle<Map>(transition)));
4476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ Push(r2, r0);
4486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ TailCallExternalReference(
449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu           ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)),
450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu           3, 1);
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (transition != NULL) {
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the map of the object; no write barrier updating is
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // needed because the map is never in new space.
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(ip, Operand(Handle<Map>(transition)));
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust for the number of properties stored in the object. Even in the
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // face of a transition we can use the old map here because the size of the
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object and the number of in-object properties is not going to change.
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index -= object->map()->inobject_properties();
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set the property straight into the object.
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = object->map()->instance_size() + (index * kPointerSize);
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r0, FieldMemOperand(receiver_reg, offset));
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Skip updating write barrier if storing a smi.
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r0, Operand(kSmiTagMask));
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &exit);
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
4769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    // Pass the now unused name_reg as a scratch register.
4779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ RecordWrite(receiver_reg, Operand(offset), name_reg, scratch);
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Write to the properties array.
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the properties array
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r0, FieldMemOperand(scratch, offset));
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Skip updating write barrier if storing a smi.
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r0, Operand(kSmiTagMask));
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &exit);
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Ok to clobber receiver_reg and name_reg, since we return.
4919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ RecordWrite(scratch, Operand(offset), name_reg, receiver_reg);
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the value (register r0).
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&exit);
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* code = NULL;
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kind == Code::LOAD_IC) {
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    code = Builtins::builtin(Builtins::LoadIC_Miss);
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(code);
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkestatic void GenerateCallFunction(MacroAssembler* masm,
5154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                 Object* object,
5164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                 const ParameterCount& arguments,
5174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                 Label* miss) {
5184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // ----------- S t a t e -------------
5194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- r0: receiver
5204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- r1: function to call
5214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // -----------------------------------
5224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Check that the function really is a function.
5244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ BranchOnSmi(r1, miss);
525402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
5264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ b(ne, miss);
5274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Patch the receiver on the stack with the global proxy if
5294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // necessary.
5304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (object->IsGlobalObject()) {
5314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
5324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize));
5334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
5344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Invoke the function.
5364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ InvokeFunction(r1, arguments, JUMP_FUNCTION);
5374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
5384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkestatic void PushInterceptorArguments(MacroAssembler* masm,
5414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                     Register receiver,
5424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                     Register holder,
5434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                     Register name,
5444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                     JSObject* holder_obj) {
5454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(name);
5464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
5474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ASSERT(!Heap::InNewSpace(interceptor));
5486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register scratch = name;
5494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ mov(scratch, Operand(Handle<Object>(interceptor)));
5504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(scratch);
5516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(receiver);
5526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(holder);
5534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ ldr(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset));
5544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(scratch);
5554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
5564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkestatic void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
5594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                                   Register receiver,
5604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                                   Register holder,
5614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                                   Register name,
5624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                                   JSObject* holder_obj) {
5634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
5644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  ExternalReference ref =
5664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly));
5674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ mov(r0, Operand(5));
5684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ mov(r1, Operand(ref));
5694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  CEntryStub stub(1);
5714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ CallStub(&stub);
5724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
5734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
5756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Reserves space for the extra arguments to FastHandleApiCall in the
5766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// caller's frame.
5776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block//
5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// These arguments are set by CheckPrototypes and GenerateFastApiCall.
5796ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void ReserveSpaceForFastApiCall(MacroAssembler* masm,
5806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                       Register scratch) {
5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(scratch, Operand(Smi::FromInt(0)));
5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(scratch);
5836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(scratch);
5846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(scratch);
5856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(scratch);
5866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Undoes the effects of ReserveSpaceForFastApiCall.
5906ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void FreeSpaceForFastApiCall(MacroAssembler* masm) {
5916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Drop(4);
5926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generates call to FastHandleApiCall builtin.
5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void GenerateFastApiCall(MacroAssembler* masm,
5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                const CallOptimization& optimization,
5986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                int argc) {
5996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the function and setup the context.
6006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  JSFunction* function = optimization.constant_function();
6018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(r5, Operand(Handle<JSFunction>(function)));
6028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset));
6036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Pass the additional arguments FastHandleApiCall expects.
6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool info_loaded = false;
6066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* callback = optimization.api_call_info()->callback();
6076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (Heap::InNewSpace(callback)) {
6086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info_loaded = true;
6096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info()));
6108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r7, FieldMemOperand(r0, CallHandlerInfo::kCallbackOffset));
6116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
6128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Move(r7, Handle<Object>(callback));
6136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* call_data = optimization.api_call_info()->data();
6156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (Heap::InNewSpace(call_data)) {
6166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!info_loaded) {
6176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info()));
6186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
6198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset));
6206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
6218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Move(r6, Handle<Object>(call_data));
6226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ add(sp, sp, Operand(1 * kPointerSize));
6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ stm(ia, sp, r5.bit() | r6.bit() | r7.bit());
6266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ sub(sp, sp, Operand(1 * kPointerSize));
6276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set the number of arguments.
6296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r0, Operand(argc + 4));
6306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Jump to the fast api call builtin (tail call).
6326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Code> code = Handle<Code>(
6336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Builtins::builtin(Builtins::FastHandleApiCall));
6346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ParameterCount expected(0);
6356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ InvokeCode(code, expected, expected,
6366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                RelocInfo::CODE_TARGET, JUMP_FUNCTION);
6376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6406ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CallInterceptorCompiler BASE_EMBEDDED {
6416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
6426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallInterceptorCompiler(StubCompiler* stub_compiler,
6436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          const ParameterCount& arguments,
6446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          Register name)
6456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : stub_compiler_(stub_compiler),
6466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        arguments_(arguments),
6476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        name_(name) {}
6486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Compile(MacroAssembler* masm,
6506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               JSObject* object,
6516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               JSObject* holder,
6526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               String* name,
6536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               LookupResult* lookup,
6546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Register receiver,
6556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Register scratch1,
6566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Register scratch2,
6573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch               Register scratch3,
6586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Label* miss) {
6596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(holder->HasNamedInterceptor());
6606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
6616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Check that the receiver isn't a smi.
6636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ BranchOnSmi(receiver, miss);
6646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CallOptimization optimization(lookup);
6666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (optimization.is_constant_call()) {
6686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      CompileCacheable(masm,
6696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       object,
6706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       receiver,
6716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       scratch1,
6726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       scratch2,
6733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                       scratch3,
6746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       holder,
6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       lookup,
6766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       name,
6776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       optimization,
6786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       miss);
6796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
6806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      CompileRegular(masm,
6816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     object,
6826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     receiver,
6836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     scratch1,
6846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     scratch2,
6853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                     scratch3,
6866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     name,
6876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     holder,
6886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     miss);
6896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
6906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
6936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void CompileCacheable(MacroAssembler* masm,
6946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       JSObject* object,
6956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       Register receiver,
6966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       Register scratch1,
6976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       Register scratch2,
6983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                       Register scratch3,
699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                       JSObject* interceptor_holder,
7006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       LookupResult* lookup,
7016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       String* name,
7026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       const CallOptimization& optimization,
7036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       Label* miss_label) {
7046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(optimization.is_constant_call());
7056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(!lookup->holder()->IsGlobalObject());
7066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int depth1 = kInvalidProtoDepth;
7086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int depth2 = kInvalidProtoDepth;
7096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool can_do_fast_api_call = false;
7106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (optimization.is_simple_api_call() &&
7116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block       !lookup->holder()->IsGlobalObject()) {
712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke     depth1 =
713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke         optimization.GetPrototypeDepthOfExpectedType(object,
714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                                      interceptor_holder);
7156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block     if (depth1 == kInvalidProtoDepth) {
716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke       depth2 =
717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke           optimization.GetPrototypeDepthOfExpectedType(interceptor_holder,
718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                                        lookup->holder());
7196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block     }
7206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block     can_do_fast_api_call = (depth1 != kInvalidProtoDepth) ||
7216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            (depth2 != kInvalidProtoDepth);
7226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ IncrementCounter(&Counters::call_const_interceptor, 1,
7256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      scratch1, scratch2);
7266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
7286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1,
7296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          scratch1, scratch2);
7306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ReserveSpaceForFastApiCall(masm, scratch1);
7316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Check that the maps from receiver to interceptor's holder
734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // haven't changed and thus we can invoke interceptor.
7356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label miss_cleanup;
7366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
7376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register holder =
7387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        stub_compiler_->CheckPrototypes(object, receiver,
7397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                        interceptor_holder, scratch1,
7403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                        scratch2, scratch3, name, depth1, miss);
7416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke an interceptor and if it provides a value,
743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // branch to |regular_invoke|.
7446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Label regular_invoke;
745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2,
7466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        &regular_invoke);
7476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Interceptor returned nothing for this property.  Try to use cached
749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // constant function.
7506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Check that the maps from interceptor's holder to constant function's
752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // holder haven't changed and thus we can use cached constant function.
7537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (interceptor_holder != lookup->holder()) {
7547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
7557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                      lookup->holder(), scratch1,
7563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                      scratch2, scratch3, name, depth2, miss);
7577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
7587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // CheckPrototypes has a side effect of fetching a 'holder'
7597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // for API (object which is instanceof for the signature).  It's
7607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // safe to omit it here, as if present, it should be fetched
7617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // by the previous CheckPrototypes.
7627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(depth2 == kInvalidProtoDepth);
7637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
7646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke function.
7666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
7676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      GenerateFastApiCall(masm, optimization, arguments_.immediate());
7686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
7696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ InvokeFunction(optimization.constant_function(), arguments_,
7706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        JUMP_FUNCTION);
7716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Deferred code for fast API call case---clean preallocated space.
7746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
7756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ bind(&miss_cleanup);
7766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FreeSpaceForFastApiCall(masm);
7776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ b(miss_label);
7786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke a regular function.
7816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ bind(&regular_invoke);
7826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (can_do_fast_api_call) {
7836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FreeSpaceForFastApiCall(masm);
7846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void CompileRegular(MacroAssembler* masm,
7886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      JSObject* object,
7896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Register receiver,
7906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Register scratch1,
7916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Register scratch2,
7923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                      Register scratch3,
7936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      String* name,
794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                      JSObject* interceptor_holder,
7956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      Label* miss_label) {
7966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Register holder =
797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
7983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                        scratch1, scratch2, scratch3, name,
7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                        miss_label);
8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Call a runtime function to load the interceptor property.
8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ EnterInternalFrame();
8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Save the name_ register across the call.
8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ push(name_);
8056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    PushInterceptorArguments(masm,
8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             receiver,
8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             holder,
8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             name_,
810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                             interceptor_holder);
8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallExternalReference(
8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          ExternalReference(
8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          5);
8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Restore the name_ register.
8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(name_);
8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ LeaveInternalFrame();
8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void LoadWithInterceptor(MacroAssembler* masm,
8236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register receiver,
8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register holder,
8256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           JSObject* holder_obj,
8266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Register scratch,
8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           Label* interceptor_succeeded) {
8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ EnterInternalFrame();
8296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ Push(holder, name_);
8306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CompileCallLoadPropertyWithInterceptor(masm,
8326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                           receiver,
8336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                           holder,
8346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                           name_,
8356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                           holder_obj);
8366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(name_);  // Restore the name.
8386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ pop(receiver);  // Restore the holder.
8396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ LeaveInternalFrame();
8406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // If interceptor returns no-result sentinel, call the constant function.
8426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
8436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ cmp(r0, scratch);
8446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ b(ne, interceptor_succeeded);
8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StubCompiler* stub_compiler_;
8486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const ParameterCount& arguments_;
8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register name_;
8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
8516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generate code to check that a global property cell is empty. Create
8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the property cell at compilation time if no cell exists for the
8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property.
8565913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell(
8575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    MacroAssembler* masm,
8585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    GlobalObject* global,
8595913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    String* name,
8605913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Register scratch,
8615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Label* miss) {
8625913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* probe;
8635913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  { MaybeObject* maybe_probe = global->EnsurePropertyCell(name);
8645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_probe->ToObject(&probe)) return maybe_probe;
8655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
8666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
8676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(cell->value()->IsTheHole());
8686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(scratch, Operand(Handle<Object>(cell)));
8696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(scratch,
8706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block         FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
8716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
8726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(scratch, ip);
8736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ b(ne, miss);
8746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return cell;
8756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm())
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister StubCompiler::CheckPrototypes(JSObject* object,
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register object_reg,
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       JSObject* holder,
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register holder_reg,
8863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Register scratch1,
8873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Register scratch2,
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       String* name,
889402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                       int save_at_depth,
8903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Label* miss) {
8913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Make sure there's no overlap between holder and object registers.
8923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
8933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
8943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch         && !scratch2.is(scratch1));
8953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
8963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Keep track of the current object in register reg.
8973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register reg = object_reg;
8983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  int depth = 0;
8993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
9003bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (save_at_depth == depth) {
9013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ str(reg, MemOperand(sp));
9023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
9033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
9043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check the maps in the prototype chain.
9053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Traverse the prototype chain from the object and do map checks.
9063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  JSObject* current = object;
9073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  while (current != holder) {
9083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    depth++;
9093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
9103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Only global objects and objects that do not require access
9113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // checks are allowed in stubs.
9123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
9133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
9143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    JSObject* prototype = JSObject::cast(current->GetPrototype());
9153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    if (!current->HasFastProperties() &&
9163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        !current->IsJSGlobalObject() &&
9173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        !current->IsJSGlobalProxy()) {
9183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      if (!name->IsSymbol()) {
9195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        MaybeObject* lookup_result = Heap::LookupSymbol(name);
9203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        if (lookup_result->IsFailure()) {
9213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch          set_failure(Failure::cast(lookup_result));
9223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch          return reg;
9233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        } else {
9245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck          name = String::cast(lookup_result->ToObjectUnchecked());
9253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        }
9263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      }
9273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      ASSERT(current->property_dictionary()->FindEntry(name) ==
9283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch             StringDictionary::kNotFound);
9293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
9303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      GenerateDictionaryNegativeLookup(masm(),
9313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       miss,
9323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       reg,
9333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       name,
9343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       scratch1,
9353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       scratch2);
9363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
9373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      reg = holder_reg;  // from now the object is in holder_reg
9383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
9393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    } else {
9403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Get the map of the current object.
9413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
9423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ cmp(scratch1, Operand(Handle<Map>(current->map())));
9433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
9443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Branch on the result of the map check.
9453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ b(ne, miss);
9463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
9473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // Check access rights to the global object.  This has to happen
9483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // after the map check so that we know that the object is
9493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      // actually a global object.
9503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      if (current->IsJSGlobalProxy()) {
9513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        __ CheckAccessGlobalProxy(reg, scratch1, miss);
9523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        // Restore scratch register to be the map of the object.  In the
9533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        // new space case below, we load the prototype from the map in
9543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        // the scratch register.
9553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
9563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      }
9573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
9583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      reg = holder_reg;  // from now the object is in holder_reg
9593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      if (Heap::InNewSpace(prototype)) {
9603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        // The prototype is in new space; we cannot store a reference
9613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        // to it in the code. Load it from the map.
9623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
9633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      } else {
9643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        // The prototype is in old space; load it directly.
9653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        __ mov(reg, Operand(Handle<JSObject>(prototype)));
9663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      }
9673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    }
9683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
9693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    if (save_at_depth == depth) {
9703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ str(reg, MemOperand(sp));
9713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    }
9723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
9733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    // Go to the next object in the prototype chain.
9743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    current = prototype;
9753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
9763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
9773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check the holder map.
9783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
9793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ cmp(scratch1, Operand(Handle<Map>(current->map())));
9803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ b(ne, miss);
9813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
9823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Log the check depth.
9833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  LOG(IntEvent("check-maps-depth", depth + 1));
9843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
9853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Perform security check for access to the global object and return
9863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // the holder register.
9873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(current == holder);
9883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
9893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (current->IsJSGlobalProxy()) {
9903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ CheckAccessGlobalProxy(reg, scratch1, miss);
9913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we've skipped any global objects, it's not enough to verify
9946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // that their maps haven't changed.  We also need to check that the
9956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // property cell for the property is still empty.
9963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  current = object;
9973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  while (current != holder) {
9983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    if (current->IsGlobalObject()) {
9995913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      MaybeObject* cell = GenerateCheckPropertyCell(masm(),
10005913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    GlobalObject::cast(current),
10015913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    name,
10025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    scratch1,
10035913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    miss);
10046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (cell->IsFailure()) {
10056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        set_failure(Failure::cast(cell));
10063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        return reg;
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
10093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    current = JSObject::cast(current->GetPrototype());
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1012402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Return the register containing the holder.
10133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  return reg;
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadField(JSObject* object,
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     JSObject* holder,
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register receiver,
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch1,
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch2,
10223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                     Register scratch3,
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     int index,
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     String* name,
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Label* miss) {
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver, Operand(kSmiTagMask));
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, miss);
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register reg =
10323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3,
10333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                      name, miss);
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), r0, reg, holder, index);
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadConstant(JSObject* object,
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        JSObject* holder,
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register receiver,
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch1,
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch2,
10443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                        Register scratch3,
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Object* value,
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        String* name,
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* miss) {
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver, Operand(kSmiTagMask));
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, miss);
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register reg =
10543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      CheckPrototypes(object, receiver, holder,
10553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                      scratch1, scratch2, scratch3, name, miss);
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the constant value.
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(Handle<Object>(value)));
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1063e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkebool StubCompiler::GenerateLoadCallback(JSObject* object,
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        JSObject* holder,
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register receiver,
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register name_reg,
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch1,
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch2,
10693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                        Register scratch3,
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AccessorInfo* callback,
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        String* name,
1072e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Label* miss,
1073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        Failure** failure) {
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver, Operand(kSmiTagMask));
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, miss);
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register reg =
10803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3,
10813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                      name, miss);
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the arguments on the JS stack of the caller.
10846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(receiver);  // Receiver.
10858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(scratch3, Operand(Handle<AccessorInfo>(callback)));  // callback data
10868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(ip, FieldMemOperand(scratch3, AccessorInfo::kDataOffset));
10878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Push(reg, ip, scratch3, name_reg);
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference load_callback_property =
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
10926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(load_callback_property, 5, 1);
1093e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1094e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return true;
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadInterceptor(JSObject* object,
10997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           JSObject* interceptor_holder,
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           LookupResult* lookup,
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register name_reg,
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch1,
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch2,
11053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                           Register scratch3,
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           String* name,
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss) {
11087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(interceptor_holder->HasNamedInterceptor());
11097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
11107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the receiver isn't a smi.
11127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ BranchOnSmi(receiver, miss);
11137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // So far the most popular follow ups for interceptor loads are FIELD
11157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // and CALLBACKS, so inline only them, other cases may be added
11167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // later.
11177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  bool compile_followup_inline = false;
11187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (lookup->IsProperty() && lookup->IsCacheable()) {
11197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == FIELD) {
11207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      compile_followup_inline = true;
11217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else if (lookup->type() == CALLBACKS &&
11227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        lookup->GetCallbackObject()->IsAccessorInfo() &&
11237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) {
11247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      compile_followup_inline = true;
11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
11277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (compile_followup_inline) {
11297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Compile the interceptor call, followed by inline code to load the
11307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // property from further up the prototype chain if the call fails.
11317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps haven't changed.
11327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
11333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          scratch1, scratch2, scratch3,
11343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          name, miss);
11357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
11367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Save necessary data before invoking an interceptor.
11387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Requires a frame to make GC aware of pushed pointers.
11397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ EnterInternalFrame();
11407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
11427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // CALLBACKS case needs a receiver to be passed into C++ callback.
11437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ Push(receiver, holder_reg, name_reg);
11447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
11457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ Push(holder_reg, name_reg);
11467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
11477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Invoke an interceptor.  Note: map checks from receiver to
11497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // interceptor's holder has been compiled before (see a caller
11507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // of this method.)
11517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    CompileCallLoadPropertyWithInterceptor(masm(),
11527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           receiver,
11537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           holder_reg,
11547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           name_reg,
11557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           interceptor_holder);
11567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check if interceptor provided a value for property.  If it's
11587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // the case, return immediately.
11597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Label interceptor_failed;
11607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex);
11617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ cmp(r0, scratch1);
11627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ b(eq, &interceptor_failed);
11637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ LeaveInternalFrame();
11647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ Ret();
11657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ bind(&interceptor_failed);
11677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ pop(name_reg);
11687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ pop(holder_reg);
11697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
11707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ pop(receiver);
11717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
11727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ LeaveInternalFrame();
11747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps from interceptor's holder to lookup's holder
11767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // haven't changed.  And load lookup's holder into |holder| register.
11777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (interceptor_holder != lookup->holder()) {
11787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      holder_reg = CheckPrototypes(interceptor_holder,
11797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   holder_reg,
11807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   lookup->holder(),
11817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch1,
11827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch2,
11833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                   scratch3,
11847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   name,
11857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   miss);
11867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == FIELD) {
11897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found FIELD property in prototype chain of interceptor's holder.
11907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Retrieve a field from field's holder.
11917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      GenerateFastPropertyLoad(masm(), r0, holder_reg,
11927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                               lookup->holder(), lookup->GetFieldIndex());
11937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ Ret();
11947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found CALLBACKS property in prototype chain of interceptor's
11967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // holder.
11977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(lookup->type() == CALLBACKS);
11987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
11997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
12007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(callback != NULL);
12017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(callback->getter() != NULL);
12027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Tail call to runtime.
12047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Important invariant in CALLBACKS case: the code above must be
12057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // structured to never clobber |receiver| register.
12067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ Move(scratch2, Handle<AccessorInfo>(callback));
12077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // holder_reg is either receiver or scratch1.
12087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      if (!receiver.is(holder_reg)) {
12097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        ASSERT(scratch1.is(holder_reg));
12108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ Push(receiver, holder_reg);
12118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ ldr(scratch3,
12128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang               FieldMemOperand(scratch2, AccessorInfo::kDataOffset));
12138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ Push(scratch3, scratch2, name_reg);
12147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      } else {
12157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        __ push(receiver);
12168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ ldr(scratch3,
12178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang               FieldMemOperand(scratch2, AccessorInfo::kDataOffset));
12188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ Push(holder_reg, scratch3, scratch2, name_reg);
12197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      }
12207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ExternalReference ref =
12227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
12237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ TailCallExternalReference(ref, 5, 1);
12247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
12257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {  // !compile_followup_inline
12267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Call the runtime system to load the interceptor.
12277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps haven't changed.
12287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
12293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          scratch1, scratch2, scratch3,
12303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          name, miss);
12317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    PushInterceptorArguments(masm(), receiver, holder_reg,
12327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                             name_reg, interceptor_holder);
12337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ExternalReference ref = ExternalReference(
12357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
12367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ TailCallExternalReference(ref, 5, 1);
12377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid CallStubCompiler::GenerateNameCheck(String* name, Label* miss) {
12429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (kind_ == Code::KEYED_CALL_IC) {
12439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ cmp(r2, Operand(Handle<String>(name)));
12449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ b(ne, miss);
12459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
12469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
12479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
12489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
124959151504615d929945dc59db37bf1166937748c6Steve Blockvoid CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object,
125059151504615d929945dc59db37bf1166937748c6Steve Block                                                   JSObject* holder,
125159151504615d929945dc59db37bf1166937748c6Steve Block                                                   String* name,
125259151504615d929945dc59db37bf1166937748c6Steve Block                                                   Label* miss) {
125359151504615d929945dc59db37bf1166937748c6Steve Block  ASSERT(holder->IsGlobalObject());
125459151504615d929945dc59db37bf1166937748c6Steve Block
125559151504615d929945dc59db37bf1166937748c6Steve Block  // Get the number of arguments.
125659151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
125759151504615d929945dc59db37bf1166937748c6Steve Block
125859151504615d929945dc59db37bf1166937748c6Steve Block  // Get the receiver from the stack.
125959151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
126059151504615d929945dc59db37bf1166937748c6Steve Block
126159151504615d929945dc59db37bf1166937748c6Steve Block  // If the object is the holder then we know that it's a global
126259151504615d929945dc59db37bf1166937748c6Steve Block  // object which can only happen for contextual calls. In this case,
126359151504615d929945dc59db37bf1166937748c6Steve Block  // the receiver cannot be a smi.
126459151504615d929945dc59db37bf1166937748c6Steve Block  if (object != holder) {
126559151504615d929945dc59db37bf1166937748c6Steve Block    __ tst(r0, Operand(kSmiTagMask));
126659151504615d929945dc59db37bf1166937748c6Steve Block    __ b(eq, miss);
126759151504615d929945dc59db37bf1166937748c6Steve Block  }
126859151504615d929945dc59db37bf1166937748c6Steve Block
126959151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the maps haven't changed.
127059151504615d929945dc59db37bf1166937748c6Steve Block  CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss);
127159151504615d929945dc59db37bf1166937748c6Steve Block}
127259151504615d929945dc59db37bf1166937748c6Steve Block
127359151504615d929945dc59db37bf1166937748c6Steve Block
127459151504615d929945dc59db37bf1166937748c6Steve Blockvoid CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
127559151504615d929945dc59db37bf1166937748c6Steve Block                                                    JSFunction* function,
127659151504615d929945dc59db37bf1166937748c6Steve Block                                                    Label* miss) {
127759151504615d929945dc59db37bf1166937748c6Steve Block  // Get the value from the cell.
127859151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
127959151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
128059151504615d929945dc59db37bf1166937748c6Steve Block
128159151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the cell contains the same function.
128259151504615d929945dc59db37bf1166937748c6Steve Block  if (Heap::InNewSpace(function)) {
128359151504615d929945dc59db37bf1166937748c6Steve Block    // We can't embed a pointer to a function in new space so we have
128459151504615d929945dc59db37bf1166937748c6Steve Block    // to verify that the shared function info is unchanged. This has
128559151504615d929945dc59db37bf1166937748c6Steve Block    // the nice side effect that multiple closures based on the same
128659151504615d929945dc59db37bf1166937748c6Steve Block    // function can all use this call IC. Before we load through the
128759151504615d929945dc59db37bf1166937748c6Steve Block    // function, we have to verify that it still is a function.
128859151504615d929945dc59db37bf1166937748c6Steve Block    __ tst(r1, Operand(kSmiTagMask));
128959151504615d929945dc59db37bf1166937748c6Steve Block    __ b(eq, miss);
129059151504615d929945dc59db37bf1166937748c6Steve Block    __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
129159151504615d929945dc59db37bf1166937748c6Steve Block    __ b(ne, miss);
129259151504615d929945dc59db37bf1166937748c6Steve Block
129359151504615d929945dc59db37bf1166937748c6Steve Block    // Check the shared function info. Make sure it hasn't changed.
129459151504615d929945dc59db37bf1166937748c6Steve Block    __ Move(r3, Handle<SharedFunctionInfo>(function->shared()));
129559151504615d929945dc59db37bf1166937748c6Steve Block    __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
129659151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(r4, r3);
129759151504615d929945dc59db37bf1166937748c6Steve Block    __ b(ne, miss);
129859151504615d929945dc59db37bf1166937748c6Steve Block  } else {
129959151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(r1, Operand(Handle<JSFunction>(function)));
130059151504615d929945dc59db37bf1166937748c6Steve Block    __ b(ne, miss);
130159151504615d929945dc59db37bf1166937748c6Steve Block  }
130259151504615d929945dc59db37bf1166937748c6Steve Block}
130359151504615d929945dc59db37bf1166937748c6Steve Block
130459151504615d929945dc59db37bf1166937748c6Steve Block
13055913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::GenerateMissBranch() {
13065913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* obj;
13075913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  { MaybeObject* maybe_obj =
13085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        StubCache::ComputeCallMiss(arguments().immediate(), kind_);
13095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
13105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1311bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
1312bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  return obj;
13137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13165913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
13175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                JSObject* holder,
13185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                int index,
13195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                String* name) {
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1321402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r2    : name
1322402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- lr    : return address
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
13279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver of the function from the stack into r0.
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(r0, Operand(kSmiTagMask));
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &miss);
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do the right check and compute the holder register.
13373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss);
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  GenerateCallFunction(masm(), object, arguments(), &miss);
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
13445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* obj;
13455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  { MaybeObject* maybe_obj = GenerateMissBranch();
13465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
13475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13545913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
13555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    JSObject* holder,
13565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    JSGlobalPropertyCell* cell,
13575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    JSFunction* function,
13585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    String* name) {
13596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
13606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r2    : name
13616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- lr    : return address
13628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
13638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- ...
13648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[argc * 4]           : receiver
13656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
13666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
136759151504615d929945dc59db37bf1166937748c6Steve Block  // If object is not an array, bail out to regular call.
136859151504615d929945dc59db37bf1166937748c6Steve Block  if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value();
13696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
13716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
13739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
13748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register receiver = r1;
13758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
13766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack
13776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
13788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
13818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ BranchOnSmi(receiver, &miss);
13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the maps haven't changed.
13848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CheckPrototypes(JSObject::cast(object), receiver,
13858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                  holder, r3, r0, r4, name, &miss);
13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (argc == 0) {
13888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    // Nothing to do, just return the length.
13898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
13908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Drop(argc + 1);
13918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Ret();
13928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  } else {
13938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    Label call_builtin;
13948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
13958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    Register elements = r3;
13968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    Register end_elements = r5;
13978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
13988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    // Get the elements array of the object.
13998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
14008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    // Check that the elements are in fast mode and writable.
14028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ CheckMap(elements, r0,
14038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                Heap::kFixedArrayMapRootIndex, &call_builtin, true);
14048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    if (argc == 1) {  // Otherwise fall through to call the builtin.
14068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      Label exit, with_write_barrier, attempt_to_grow_elements;
14078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Get the array's length into r0 and calculate new length.
14098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
14108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      STATIC_ASSERT(kSmiTagSize == 1);
14118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      STATIC_ASSERT(kSmiTag == 0);
14128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(r0, r0, Operand(Smi::FromInt(argc)));
14138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Get the element's length.
14158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
14168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Check if we could survive without allocation.
14188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ cmp(r0, r4);
14198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ b(gt, &attempt_to_grow_elements);
14208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Save new length.
14228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
14238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Push the element.
14258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
14268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // We may need a register containing the address end_elements below,
14278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // so write back the value in end_elements.
14288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(end_elements, elements,
14298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang             Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
14308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      const int kEndElementsOffset =
14318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang          FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
14328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
14338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Check for a smi.
14358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ BranchOnNotSmi(r4, &with_write_barrier);
14368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ bind(&exit);
14378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Drop(argc + 1);
14388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Ret();
14398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ bind(&with_write_barrier);
14418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ InNewSpace(elements, r4, eq, &exit);
14428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ RecordWriteHelper(elements, end_elements, r4);
14438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Drop(argc + 1);
14448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Ret();
14458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ bind(&attempt_to_grow_elements);
14478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // r0: array's length + 1.
14488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // r4: elements' length.
14498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      if (!FLAG_inline_new) {
14518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ b(&call_builtin);
14528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      }
14538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      ExternalReference new_space_allocation_top =
14558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang          ExternalReference::new_space_allocation_top_address();
14568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      ExternalReference new_space_allocation_limit =
14578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang          ExternalReference::new_space_allocation_limit_address();
14588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      const int kAllocationDelta = 4;
14608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Load top and check if it is the end of elements.
14618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(end_elements, elements,
14628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang             Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
14638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(end_elements, end_elements, Operand(kEndElementsOffset));
14648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ mov(r7, Operand(new_space_allocation_top));
14658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ ldr(r6, MemOperand(r7));
14668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ cmp(end_elements, r6);
14678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ b(ne, &call_builtin);
14688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ mov(r9, Operand(new_space_allocation_limit));
14708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ ldr(r9, MemOperand(r9));
14718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(r6, r6, Operand(kAllocationDelta * kPointerSize));
14728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ cmp(r6, r9);
14738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ b(hi, &call_builtin);
14748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // We fit and could grow elements.
14768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Update new_space_allocation_top.
14778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r6, MemOperand(r7));
14788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Push the argument.
14798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ ldr(r6, MemOperand(sp, (argc - 1) * kPointerSize));
14808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r6, MemOperand(end_elements));
14818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Fill the rest with holes.
14828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
14838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      for (int i = 1; i < kAllocationDelta; i++) {
14848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        __ str(r6, MemOperand(end_elements, i * kPointerSize));
14858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      }
14868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Update elements' and array's sizes.
14888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
14898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta)));
14908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
14918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
14928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      // Elements are in new space, so write barrier is not required.
14938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Drop(argc + 1);
14948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ Ret();
14958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    }
14968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ bind(&call_builtin);
14978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
14988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 argc + 1,
14998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 1);
15008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Handle call cache miss.
15036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
15045913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* obj;
15055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  { MaybeObject* maybe_obj = GenerateMissBranch();
15065913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
15075913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
151025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
15116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15145913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
15155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   JSObject* holder,
15165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   JSGlobalPropertyCell* cell,
15175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   JSFunction* function,
15185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   String* name) {
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1520402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r2    : name
1521402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- lr    : return address
15228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
15238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- ...
15248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[argc * 4]           : receiver
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
15266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
152759151504615d929945dc59db37bf1166937748c6Steve Block  // If object is not an array, bail out to regular call.
152859151504615d929945dc59db37bf1166937748c6Steve Block  if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value();
15296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label miss, return_undefined, call_builtin;
15318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register receiver = r1;
15338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register elements = r3;
1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
15369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
15398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
15428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ BranchOnSmi(receiver, &miss);
15436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the maps haven't changed.
15458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CheckPrototypes(JSObject::cast(object),
15468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                  receiver, holder, elements, r4, r0, name, &miss);
15478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Get the elements array of the object.
15498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
15506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check that the elements are in fast mode and writable.
15528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ CheckMap(elements, r0, Heap::kFixedArrayMapRootIndex, &call_builtin, true);
15538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Get the array's length into r4 and calculate new length.
15558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
15568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC);
15578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(lt, &return_undefined);
15588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Get the last element.
15608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
15618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(kSmiTagSize == 1);
15628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(kSmiTag == 0);
15638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We can't address the last element in one operation. Compute the more
15648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // expensive shift first, and use an offset later on.
15658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ add(elements, elements, Operand(r4, LSL, kPointerSizeLog2 - kSmiTagSize));
15668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r0, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag));
15678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(r0, r6);
15688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(eq, &call_builtin);
15698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Set the array's length.
15718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
15728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Fill with the hole.
15748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(r6, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag));
15758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(argc + 1);
15768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
15778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&return_undefined);
15798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
15808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(argc + 1);
15818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
15828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
15838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&call_builtin);
15846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop),
15856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               argc + 1,
15866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               1);
15876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Handle call cache miss.
15896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
15905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* obj;
15915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  { MaybeObject* maybe_obj = GenerateMissBranch();
15925913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
15935913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
15946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
159625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
15976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16005913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
160159151504615d929945dc59db37bf1166937748c6Steve Block    Object* object,
160259151504615d929945dc59db37bf1166937748c6Steve Block    JSObject* holder,
160359151504615d929945dc59db37bf1166937748c6Steve Block    JSGlobalPropertyCell* cell,
160459151504615d929945dc59db37bf1166937748c6Steve Block    JSFunction* function,
160559151504615d929945dc59db37bf1166937748c6Steve Block    String* name) {
160680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ----------- S t a t e -------------
160780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- r2                     : function name
160880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- lr                     : return address
160980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
161080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- ...
161180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- sp[argc * 4]           : receiver
161280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // -----------------------------------
161380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
161480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If object is not a string, bail out to regular call.
161559151504615d929945dc59db37bf1166937748c6Steve Block  if (!object->IsString() || cell != NULL) return Heap::undefined_value();
161680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
161780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const int argc = arguments().immediate();
161880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
161980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label miss;
162080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label index_out_of_range;
162180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateNameCheck(name, &miss);
162280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
162380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the maps starting from the prototype haven't changed.
162480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateDirectLoadGlobalFunctionPrototype(masm(),
162580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                            Context::STRING_FUNCTION_INDEX,
16260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            r0,
16270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
162880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(object != holder);
162980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder,
163080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                  r1, r3, r4, name, &miss);
163180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
163280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register receiver = r1;
163380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register index = r4;
163480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register scratch = r3;
163580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register result = r0;
163680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
163780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (argc > 0) {
163880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
163980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
164080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
164180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
164280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
164380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  StringCharCodeAtGenerator char_code_at_generator(receiver,
164480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   index,
164580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   scratch,
164680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   result,
164780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   &miss,  // When not a string.
164880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   &miss,  // When not a number.
164980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   &index_out_of_range,
165080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                   STRING_INDEX_IS_NUMBER);
165180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  char_code_at_generator.GenerateFast(masm());
165280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Drop(argc + 1);
165380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Ret();
165480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
165580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ICRuntimeCallHelper call_helper;
165680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  char_code_at_generator.GenerateSlow(masm(), call_helper);
165780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
165880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&index_out_of_range);
165980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ LoadRoot(r0, Heap::kNanValueRootIndex);
166080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Drop(argc + 1);
166180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Ret();
166280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
166380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&miss);
16645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* obj;
16655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  { MaybeObject* maybe_obj = GenerateMissBranch();
16665913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
16675913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
166880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
166980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Return the generated code.
167080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return GetCode(function);
16717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
16727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16745913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileStringCharAtCall(
16755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Object* object,
16765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    JSObject* holder,
16775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    JSGlobalPropertyCell* cell,
16785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    JSFunction* function,
16795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    String* name) {
168080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // ----------- S t a t e -------------
168180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- r2                     : function name
168280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- lr                     : return address
168380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
168480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- ...
168580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //  -- sp[argc * 4]           : receiver
168680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // -----------------------------------
168780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
168880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If object is not a string, bail out to regular call.
168959151504615d929945dc59db37bf1166937748c6Steve Block  if (!object->IsString() || cell != NULL) return Heap::undefined_value();
169080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
169180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const int argc = arguments().immediate();
169280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
169380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label miss;
169480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label index_out_of_range;
169580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
169680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateNameCheck(name, &miss);
169780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
169880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the maps starting from the prototype haven't changed.
169980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  GenerateDirectLoadGlobalFunctionPrototype(masm(),
170080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                            Context::STRING_FUNCTION_INDEX,
17010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            r0,
17020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
170380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(object != holder);
170480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder,
170580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                  r1, r3, r4, name, &miss);
170680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
170780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register receiver = r0;
170880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register index = r4;
170980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register scratch1 = r1;
171080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register scratch2 = r3;
171180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Register result = r0;
171280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
171380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (argc > 0) {
171480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
171580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
171680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
171780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
171880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
171980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  StringCharAtGenerator char_at_generator(receiver,
172080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          index,
172180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          scratch1,
172280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          scratch2,
172380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          result,
172480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          &miss,  // When not a string.
172580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          &miss,  // When not a number.
172680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          &index_out_of_range,
172780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          STRING_INDEX_IS_NUMBER);
172880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  char_at_generator.GenerateFast(masm());
172980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Drop(argc + 1);
173080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Ret();
173180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
173280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ICRuntimeCallHelper call_helper;
173380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  char_at_generator.GenerateSlow(masm(), call_helper);
173480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
173580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&index_out_of_range);
173680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ LoadRoot(r0, Heap::kEmptyStringRootIndex);
173780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Drop(argc + 1);
173880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Ret();
173980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
174080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&miss);
17415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* obj;
17425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  { MaybeObject* maybe_obj = GenerateMissBranch();
17435913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
17445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
174580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
174680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Return the generated code.
174780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return GetCode(function);
17487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
17497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17515913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
175259151504615d929945dc59db37bf1166937748c6Steve Block    Object* object,
175359151504615d929945dc59db37bf1166937748c6Steve Block    JSObject* holder,
175459151504615d929945dc59db37bf1166937748c6Steve Block    JSGlobalPropertyCell* cell,
175559151504615d929945dc59db37bf1166937748c6Steve Block    JSFunction* function,
175659151504615d929945dc59db37bf1166937748c6Steve Block    String* name) {
175759151504615d929945dc59db37bf1166937748c6Steve Block  // ----------- S t a t e -------------
175859151504615d929945dc59db37bf1166937748c6Steve Block  //  -- r2                     : function name
175959151504615d929945dc59db37bf1166937748c6Steve Block  //  -- lr                     : return address
176059151504615d929945dc59db37bf1166937748c6Steve Block  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
176159151504615d929945dc59db37bf1166937748c6Steve Block  //  -- ...
176259151504615d929945dc59db37bf1166937748c6Steve Block  //  -- sp[argc * 4]           : receiver
176359151504615d929945dc59db37bf1166937748c6Steve Block  // -----------------------------------
176459151504615d929945dc59db37bf1166937748c6Steve Block
176559151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
176659151504615d929945dc59db37bf1166937748c6Steve Block
176759151504615d929945dc59db37bf1166937748c6Steve Block  // If the object is not a JSObject or we got an unexpected number of
176859151504615d929945dc59db37bf1166937748c6Steve Block  // arguments, bail out to the regular call.
176959151504615d929945dc59db37bf1166937748c6Steve Block  if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
177059151504615d929945dc59db37bf1166937748c6Steve Block
177159151504615d929945dc59db37bf1166937748c6Steve Block  Label miss;
177259151504615d929945dc59db37bf1166937748c6Steve Block  GenerateNameCheck(name, &miss);
177359151504615d929945dc59db37bf1166937748c6Steve Block
177459151504615d929945dc59db37bf1166937748c6Steve Block  if (cell == NULL) {
177559151504615d929945dc59db37bf1166937748c6Steve Block    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
177659151504615d929945dc59db37bf1166937748c6Steve Block
177759151504615d929945dc59db37bf1166937748c6Steve Block    STATIC_ASSERT(kSmiTag == 0);
177859151504615d929945dc59db37bf1166937748c6Steve Block    __ tst(r1, Operand(kSmiTagMask));
177959151504615d929945dc59db37bf1166937748c6Steve Block    __ b(eq, &miss);
178059151504615d929945dc59db37bf1166937748c6Steve Block
178159151504615d929945dc59db37bf1166937748c6Steve Block    CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
178259151504615d929945dc59db37bf1166937748c6Steve Block                    &miss);
178359151504615d929945dc59db37bf1166937748c6Steve Block  } else {
178459151504615d929945dc59db37bf1166937748c6Steve Block    ASSERT(cell->value() == function);
178559151504615d929945dc59db37bf1166937748c6Steve Block    GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
178659151504615d929945dc59db37bf1166937748c6Steve Block    GenerateLoadFunctionFromCell(cell, function, &miss);
178759151504615d929945dc59db37bf1166937748c6Steve Block  }
178859151504615d929945dc59db37bf1166937748c6Steve Block
178959151504615d929945dc59db37bf1166937748c6Steve Block  // Load the char code argument.
179059151504615d929945dc59db37bf1166937748c6Steve Block  Register code = r1;
179159151504615d929945dc59db37bf1166937748c6Steve Block  __ ldr(code, MemOperand(sp, 0 * kPointerSize));
179259151504615d929945dc59db37bf1166937748c6Steve Block
179359151504615d929945dc59db37bf1166937748c6Steve Block  // Check the code is a smi.
179459151504615d929945dc59db37bf1166937748c6Steve Block  Label slow;
179559151504615d929945dc59db37bf1166937748c6Steve Block  STATIC_ASSERT(kSmiTag == 0);
179659151504615d929945dc59db37bf1166937748c6Steve Block  __ tst(code, Operand(kSmiTagMask));
179759151504615d929945dc59db37bf1166937748c6Steve Block  __ b(ne, &slow);
179859151504615d929945dc59db37bf1166937748c6Steve Block
179959151504615d929945dc59db37bf1166937748c6Steve Block  // Convert the smi code to uint16.
180059151504615d929945dc59db37bf1166937748c6Steve Block  __ and_(code, code, Operand(Smi::FromInt(0xffff)));
180159151504615d929945dc59db37bf1166937748c6Steve Block
180259151504615d929945dc59db37bf1166937748c6Steve Block  StringCharFromCodeGenerator char_from_code_generator(code, r0);
180359151504615d929945dc59db37bf1166937748c6Steve Block  char_from_code_generator.GenerateFast(masm());
180459151504615d929945dc59db37bf1166937748c6Steve Block  __ Drop(argc + 1);
180559151504615d929945dc59db37bf1166937748c6Steve Block  __ Ret();
180659151504615d929945dc59db37bf1166937748c6Steve Block
180759151504615d929945dc59db37bf1166937748c6Steve Block  ICRuntimeCallHelper call_helper;
180859151504615d929945dc59db37bf1166937748c6Steve Block  char_from_code_generator.GenerateSlow(masm(), call_helper);
180959151504615d929945dc59db37bf1166937748c6Steve Block
181059151504615d929945dc59db37bf1166937748c6Steve Block  // Tail call the full function. We do not have to patch the receiver
181159151504615d929945dc59db37bf1166937748c6Steve Block  // because the function makes no use of it.
181259151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&slow);
181359151504615d929945dc59db37bf1166937748c6Steve Block  __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
181459151504615d929945dc59db37bf1166937748c6Steve Block
181559151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&miss);
181659151504615d929945dc59db37bf1166937748c6Steve Block  // r2: function name.
18175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* obj;
18185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  { MaybeObject* maybe_obj = GenerateMissBranch();
18195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
18205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
182159151504615d929945dc59db37bf1166937748c6Steve Block
182259151504615d929945dc59db37bf1166937748c6Steve Block  // Return the generated code.
182359151504615d929945dc59db37bf1166937748c6Steve Block  return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
182459151504615d929945dc59db37bf1166937748c6Steve Block}
182559151504615d929945dc59db37bf1166937748c6Steve Block
182659151504615d929945dc59db37bf1166937748c6Steve Block
18275913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
18285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    JSObject* holder,
18295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    JSGlobalPropertyCell* cell,
18305913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    JSFunction* function,
18315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    String* name) {
18328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // ----------- S t a t e -------------
18338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- r2                     : function name
18348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- lr                     : return address
18358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
18368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- ...
18378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[argc * 4]           : receiver
18388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // -----------------------------------
18398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (!CpuFeatures::IsSupported(VFP3)) return Heap::undefined_value();
18418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CpuFeatures::Scope scope_vfp3(VFP3);
18428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int argc = arguments().immediate();
18448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If the object is not a JSObject or we got an unexpected number of
18468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // arguments, bail out to the regular call.
18478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
18488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label miss, slow;
18508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  GenerateNameCheck(name, &miss);
18518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (cell == NULL) {
18538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
18548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    STATIC_ASSERT(kSmiTag == 0);
18568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ BranchOnSmi(r1, &miss);
18578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
18598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                    &miss);
18608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  } else {
18618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    ASSERT(cell->value() == function);
18628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
18638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    GenerateLoadFunctionFromCell(cell, function, &miss);
18648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
18658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the (only) argument into r0.
18678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r0, MemOperand(sp, 0 * kPointerSize));
18688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If the argument is a smi, just return.
18708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(kSmiTag == 0);
18718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ tst(r0, Operand(kSmiTagMask));
18728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(argc + 1, eq);
18738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret(eq);
18748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, true);
18768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label wont_fit_smi, no_vfp_exception, restore_fpscr_and_return;
18788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If vfp3 is enabled, we use the fpu rounding with the RM (round towards
18808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // minus infinity) mode.
18818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the HeapNumber value.
18838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We will need access to the value in the core registers, so we load it
18848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // with ldrd and move it to the fpu. It also spares a sub instruction for
18858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // updating the HeapNumber value address, as vldr expects a multiple
18868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // of 4 offset.
18878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ldrd(r4, r5, FieldMemOperand(r0, HeapNumber::kValueOffset));
18888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmov(d1, r4, r5);
18898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
18908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Backup FPSCR.
18918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmrs(r3);
18928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Set custom FPCSR:
18938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  - Set rounding mode to "Round towards Minus Infinity"
18948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //    (ie bits [23:22] = 0b10).
18958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  - Clear vfp cumulative exception flags (bits [3:0]).
18968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  - Make sure Flush-to-zero mode control bit is unset (bit 22).
18978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bic(r9, r3,
18988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask));
18998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ orr(r9, r9, Operand(kVFPRoundToMinusInfinityBits));
19008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmsr(r9);
19018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
19028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Convert the argument to an integer.
19038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vcvt_s32_f64(s0, d1, Assembler::FPSCRRounding, al);
19048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
19058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Use vcvt latency to start checking for special cases.
19068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Get the argument exponent and clear the sign bit.
19078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bic(r6, r5, Operand(HeapNumber::kSignMask));
19088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(r6, Operand(r6, LSR, HeapNumber::kMantissaBitsInTopWord));
19098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
19108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Retrieve FPSCR and check for vfp exceptions.
19118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmrs(r9);
19128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ tst(r9, Operand(kVFPExceptionMask));
19138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&no_vfp_exception, eq);
19148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
19158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check for NaN, Infinity, and -Infinity.
19168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // They are invariant through a Math.Floor call, so just
19178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // return the original argument.
19188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ sub(r7, r6, Operand(HeapNumber::kExponentMask
19198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        >> HeapNumber::kMantissaBitsInTopWord), SetCC);
19208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&restore_fpscr_and_return, eq);
19218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // We had an overflow or underflow in the conversion. Check if we
19228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // have a big exponent.
19238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(r7, Operand(HeapNumber::kMantissaBits));
19248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If greater or equal, the argument is already round and in r0.
19258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&restore_fpscr_and_return, ge);
19268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&slow);
19278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
19288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&no_vfp_exception);
19298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Move the result back to general purpose register r0.
19308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmov(r0, s0);
19318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check if the result fits into a smi.
19328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ add(r1, r0, Operand(0x40000000), SetCC);
19338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&wont_fit_smi, mi);
19348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Tag the result.
19358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(kSmiTag == 0);
19368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
19378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
19388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check for -0.
19398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(r0, Operand(0));
19408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&restore_fpscr_and_return, ne);
19418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // r5 already holds the HeapNumber exponent.
19428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ tst(r5, Operand(HeapNumber::kSignMask));
19438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If our HeapNumber is negative it was -0, so load its address and return.
19448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Else r0 is loaded with 0, so we can also just return.
19458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r0, MemOperand(sp, 0 * kPointerSize), ne);
19468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
19478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&restore_fpscr_and_return);
19488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Restore FPSCR and return.
19498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmsr(r3);
19508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(argc + 1);
19518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
19528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
19538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&wont_fit_smi);
19548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&slow);
19558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Restore FPCSR and fall to slow case.
19568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ vmsr(r3);
19578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
19588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Tail call the full function. We do not have to patch the receiver
19598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // because the function makes no use of it.
19608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
19618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
19628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&miss);
19638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // r2: function name.
19648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  MaybeObject* obj = GenerateMissBranch();
19658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (obj->IsFailure()) return obj;
19668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
19678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Return the generated code.
19688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
19690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
19700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19725913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
19735913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  JSObject* holder,
19745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  JSGlobalPropertyCell* cell,
19755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  JSFunction* function,
19765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  String* name) {
1977f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // ----------- S t a t e -------------
1978f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- r2                     : function name
1979f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- lr                     : return address
1980f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
1981f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- ...
1982f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- sp[argc * 4]           : receiver
1983f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // -----------------------------------
1984f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1985f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const int argc = arguments().immediate();
1986f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1987f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the object is not a JSObject or we got an unexpected number of
1988f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // arguments, bail out to the regular call.
1989f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
1990f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1991f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label miss;
1992f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  GenerateNameCheck(name, &miss);
1993f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1994f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (cell == NULL) {
1995f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
1996f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1997f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
1998f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ tst(r1, Operand(kSmiTagMask));
1999f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ b(eq, &miss);
2000f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2001f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
2002f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                    &miss);
2003f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  } else {
2004f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ASSERT(cell->value() == function);
2005f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
2006f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    GenerateLoadFunctionFromCell(cell, function, &miss);
2007f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
2008f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2009f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Load the (only) argument into r0.
2010f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ldr(r0, MemOperand(sp, 0 * kPointerSize));
2011f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2012f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check if the argument is a smi.
2013f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label not_smi;
2014f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
2015f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ BranchOnNotSmi(r0, &not_smi);
2016f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2017f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Do bitwise not or do nothing depending on the sign of the
2018f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // argument.
2019f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ eor(r1, r0, Operand(r0, ASR, kBitsPerInt - 1));
2020f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2021f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Add 1 or do nothing depending on the sign of the argument.
2022f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ sub(r0, r1, Operand(r0, ASR, kBitsPerInt - 1), SetCC);
2023f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2024f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the result is still negative, go to the slow case.
2025f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // This only happens for the most negative smi.
2026f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label slow;
2027f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ b(mi, &slow);
2028f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2029f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Smi case done.
2030f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Drop(argc + 1);
2031f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Ret();
2032f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2033f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check if the argument is a heap number and load its exponent and
2034f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // sign.
2035f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&not_smi);
2036f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, true);
2037f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ldr(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset));
2038f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2039f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check the sign of the argument. If the argument is positive,
2040f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // just return it.
2041f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label negative_sign;
2042f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ tst(r1, Operand(HeapNumber::kSignMask));
2043f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ b(ne, &negative_sign);
2044f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Drop(argc + 1);
2045f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Ret();
2046f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2047f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the argument is negative, clear the sign, and return a new
2048f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // number.
2049f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&negative_sign);
2050f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ eor(r1, r1, Operand(HeapNumber::kSignMask));
2051f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
2052f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
2053f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ AllocateHeapNumber(r0, r4, r5, r6, &slow);
2054f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset));
2055f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
2056f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Drop(argc + 1);
2057f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ Ret();
2058f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2059f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Tail call the full function. We do not have to patch the receiver
2060f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // because the function makes no use of it.
2061f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&slow);
2062f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
2063f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2064f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&miss);
2065f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // r2: function name.
20665913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* obj;
20675913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  { MaybeObject* maybe_obj = GenerateMissBranch();
20685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
20695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
2070f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2071f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Return the generated code.
2072f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
2073f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
2074f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2075f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
20765913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
20775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   JSObject* holder,
20785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   JSFunction* function,
20795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   String* name,
20805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   CheckType check) {
20816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
20826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r2    : name
20836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- lr    : return address
20846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
20856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SharedFunctionInfo* function_info = function->shared();
20866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (function_info->HasCustomCallGenerator()) {
208725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    const int id = function_info->custom_call_generator_id();
20885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    MaybeObject* maybe_result = CompileCustomCall(
208959151504615d929945dc59db37bf1166937748c6Steve Block        id, object, holder, NULL, function, name);
20905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Object* result;
20915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_result->ToObject(&result)) return maybe_result;
20926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // undefined means bail out to regular compiler.
20936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!result->IsUndefined()) {
20946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return result;
20956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
20966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
20976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss_in_smi_check;
20996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss_in_smi_check);
21019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
21026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack
21036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
21046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
21056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check != NUMBER_CHECK) {
2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r1, Operand(kSmiTagMask));
21096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ b(eq, &miss_in_smi_check);
2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that it's okay not to patch the on stack receiver
2113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // unless we're doing a receiver map check.
2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallOptimization optimization(function);
21176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int depth = kInvalidProtoDepth;
21186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
21196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (check) {
2121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RECEIVER_MAP_CHECK:
21226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ IncrementCounter(&Counters::call_const, 1, r0, r3);
21236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (optimization.is_simple_api_call() && !object->IsGlobalObject()) {
21256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        depth = optimization.GetPrototypeDepthOfExpectedType(
21266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            JSObject::cast(object), holder);
21276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
21286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (depth != kInvalidProtoDepth) {
21306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ IncrementCounter(&Counters::call_const_fast_api, 1, r0, r3);
21316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        ReserveSpaceForFastApiCall(masm(), r0);
21326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
21336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the maps haven't changed.
21353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
21366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      depth, &miss);
2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Patch the receiver on the stack with the global proxy if
2139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // necessary.
2140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsGlobalObject()) {
21416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        ASSERT(depth == kInvalidProtoDepth);
2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ str(r3, MemOperand(sp, argc * kPointerSize));
2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case STRING_CHECK:
2148e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!function->IsBuiltin()) {
2149e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Calling non-builtins with a value as receiver requires boxing.
2150e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ jmp(&miss);
2151e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
2152e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a two-byte string or a symbol.
2153402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
2154e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ b(hs, &miss);
2155e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
21567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
21570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::STRING_FUNCTION_INDEX, r0, &miss);
2158402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
21593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                        r1, r4, name, &miss);
2160e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case NUMBER_CHECK: {
2164e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!function->IsBuiltin()) {
2165e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Calling non-builtins with a value as receiver requires boxing.
2166e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ jmp(&miss);
2167e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
2168e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
2169e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a smi or a heap number.
2170e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ tst(r1, Operand(kSmiTagMask));
2171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ b(eq, &fast);
2172402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE);
2173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ b(ne, &miss);
2174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
2175e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
21767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
21770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss);
2178402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
21793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                        r1, r4, name, &miss);
2180e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case BOOLEAN_CHECK: {
2185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (!function->IsBuiltin()) {
2186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Calling non-builtins with a value as receiver requires boxing.
2187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ jmp(&miss);
2188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
2189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
2190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a boolean.
2191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ LoadRoot(ip, Heap::kTrueValueRootIndex);
2192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ cmp(r1, ip);
2193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ b(eq, &fast);
2194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ LoadRoot(ip, Heap::kFalseValueRootIndex);
2195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ cmp(r1, ip);
2196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ b(ne, &miss);
2197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
2198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
21997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
22000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss);
2201402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
22023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                        r1, r4, name, &miss);
2203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (depth != kInvalidProtoDepth) {
22126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    GenerateFastApiCall(masm(), optimization, argc);
22136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
22146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
22156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
22196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (depth != kInvalidProtoDepth) {
22206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    FreeSpaceForFastApiCall(masm());
22216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
22226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
22236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss_in_smi_check);
22245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* obj;
22255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  { MaybeObject* maybe_obj = GenerateMissBranch();
22265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
22275913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
223025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22345913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
22355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                      JSObject* holder,
22365913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                      String* name) {
2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2238402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r2    : name
2239402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- lr    : return address
2240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
2243402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
22449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
22459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
22464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Get the number of arguments.
22474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  const int argc = arguments().immediate();
22484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
22494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  LookupResult lookup;
22504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  LookupPostInterceptor(holder, name, &lookup);
22514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
22526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack.
22536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
2254402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
22556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CallInterceptorCompiler compiler(this, arguments(), r2);
22566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  compiler.Compile(masm(),
22576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   object,
22586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   holder,
22596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   name,
22606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   &lookup,
22616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   r1,
22626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   r3,
22636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   r4,
22643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                   r0,
22656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   &miss);
2266402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2267402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Move returned value, the function to call, to r1.
2268402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(r1, r0);
22694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Restore receiver.
22706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
22714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
22724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  GenerateCallFunction(masm(), object, arguments(), &miss);
2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
22765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* obj;
22775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  { MaybeObject* maybe_obj = GenerateMissBranch();
22785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
22795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22865913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
22875913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                 GlobalObject* holder,
22885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                 JSGlobalPropertyCell* cell,
22895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                 JSFunction* function,
22905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                 String* name) {
2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2292402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r2    : name
2293402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- lr    : return address
2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
229559151504615d929945dc59db37bf1166937748c6Steve Block
229659151504615d929945dc59db37bf1166937748c6Steve Block  SharedFunctionInfo* function_info = function->shared();
229759151504615d929945dc59db37bf1166937748c6Steve Block  if (function_info->HasCustomCallGenerator()) {
229859151504615d929945dc59db37bf1166937748c6Steve Block    const int id = function_info->custom_call_generator_id();
22995913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    MaybeObject* maybe_result = CompileCustomCall(
230059151504615d929945dc59db37bf1166937748c6Steve Block        id, object, holder, cell, function, name);
23015913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Object* result;
23025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_result->ToObject(&result)) return maybe_result;
230359151504615d929945dc59db37bf1166937748c6Steve Block    // undefined means bail out to regular compiler.
230459151504615d929945dc59db37bf1166937748c6Steve Block    if (!result->IsUndefined()) return result;
230559151504615d929945dc59db37bf1166937748c6Steve Block  }
230659151504615d929945dc59db37bf1166937748c6Steve Block
2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateNameCheck(name, &miss);
23109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments.
2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
231459151504615d929945dc59db37bf1166937748c6Steve Block  GenerateGlobalReceiverCheck(object, holder, name, &miss);
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
231659151504615d929945dc59db37bf1166937748c6Steve Block  GenerateLoadFunctionFromCell(cell, function, &miss);
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy if
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary.
2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r3, MemOperand(sp, argc * kPointerSize));
2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup the context (function already in r1).
2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the cached code (tail call).
23296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ IncrementCounter(&Counters::call_global_inline, 1, r3, r4);
2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(function->is_compiled());
2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code(function->code());
2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(function->shared()->formal_parameter_count());
2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeCode(code, expected, arguments(),
2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                RelocInfo::CODE_TARGET, JUMP_FUNCTION);
2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3);
23395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Object* obj;
23405913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  { MaybeObject* maybe_obj = GenerateMissBranch();
23415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
23425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  }
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23495913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object,
23505913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  int index,
23515913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  Map* transition,
23525913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  String* name) {
2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
2355402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r1    : receiver
2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateStoreField(masm(),
2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     object,
2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     index,
2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     transition,
2365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                     r1, r2, r3,
2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     &miss);
2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23765913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object,
23775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                     AccessorInfo* callback,
23785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                     String* name) {
2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
2381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r1    : receiver
2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
2388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ tst(r1, Operand(kSmiTagMask));
2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &miss);
2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
2392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
2393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ cmp(r3, Operand(Handle<Map>(object->map())));
2394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
2398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ CheckAccessGlobalProxy(r1, r3, &miss);
2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2405402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(r1);  // receiver
2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ip, Operand(Handle<AccessorInfo>(callback)));  // callback info
24076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(ip, r2, r0);
2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_callback_property =
2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
24126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(store_callback_property, 4, 1);
2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24245913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
24255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                        String* name) {
2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
2428402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r1    : receiver
2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
2435402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ tst(r1, Operand(kSmiTagMask));
2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &miss);
2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
2439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
2440402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ cmp(r3, Operand(Handle<Map>(receiver->map())));
2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (receiver->IsJSGlobalProxy()) {
2445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ CheckAccessGlobalProxy(r1, r3, &miss);
2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Stub is never generated for non-global objects that require access
2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Push(r1, r2, r0);  // Receiver, name, value.
2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_ic_property =
2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
24576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(store_ic_property, 3, 1);
2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24695913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
24705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   JSGlobalPropertyCell* cell,
24715913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   String* name) {
2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
2474402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- r1    : receiver
2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
2482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r3, Operand(Handle<Map>(object->map())));
2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Store the value in the cell.
2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(Handle<JSGlobalPropertyCell>(cell)));
2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r0, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2489402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ IncrementCounter(&Counters::named_store_global_inline, 1, r4, r3);
2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2494402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ IncrementCounter(&Counters::named_store_global_inline_miss, 1, r4, r3);
2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
2496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25035913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
25045913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                      JSObject* object,
25055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                      JSObject* last) {
25066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
2507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
25086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- lr    : return address
25096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
25106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
25116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that receiver is not a smi.
25136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ tst(r0, Operand(kSmiTagMask));
25146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ b(eq, &miss);
25156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the maps of the full prototype chain.
25173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss);
25186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If the last object in the prototype chain is a global object,
25206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // check that the global property cell is empty.
25216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (last->IsGlobalObject()) {
25225913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    MaybeObject* cell = GenerateCheckPropertyCell(masm(),
25235913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  GlobalObject::cast(last),
25245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  name,
25255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  r1,
25265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  &miss);
25270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (cell->IsFailure()) {
25280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      miss.Unuse();
25290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      return cell;
25300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
25316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
25326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return undefined if maps of the full prototype chain are still the
25346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // same and no global property with this name contains a value.
25356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
25366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Ret();
25376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
25396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
25406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
25426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return GetCode(NONEXISTENT, Heap::empty_string());
25436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
25446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
25465913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object,
25475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                JSObject* holder,
25485913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                int index,
25495913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                String* name) {
2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(object, holder, r0, r3, r1, r4, index, name, &miss);
2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25665913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LoadStubCompiler::CompileLoadCallback(String* name,
25675913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   JSObject* object,
25685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   JSObject* holder,
25695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   AccessorInfo* callback) {
2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Failure* failure = Failure::InternalError();
25783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  bool success = GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4,
2579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                      callback, name, &miss, &failure);
25800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!success) {
25810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    miss.Unuse();
25820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    return failure;
25830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
2584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25935913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object,
25945913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   JSObject* holder,
25955913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   Object* value,
25965913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                   String* name) {
2597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadConstant(object, holder, r0, r3, r1, r4, value, name, &miss);
2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26135913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
26145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                      JSObject* holder,
26155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                      String* name) {
2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupResult lookup;
26244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  LookupPostInterceptor(holder, name, &lookup);
2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadInterceptor(object,
2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          holder,
2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &lookup,
2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r0,
2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r2,
2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r3,
2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r1,
26323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                          r4,
2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          name,
2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &miss);
2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26435913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
26445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                 GlobalObject* holder,
26455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                 JSGlobalPropertyCell* cell,
26465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                 String* name,
26475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                 bool is_dont_delete) {
2648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r0    : receiver
2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the object is the holder then we know that it's a global
2656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object which can only happen for contextual calls. In this case,
2657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the receiver cannot be a smi.
2658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object != holder) {
26596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ tst(r0, Operand(kSmiTagMask));
2660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &miss);
2661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
26643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss);
2665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value from the cell.
2667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
26686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
2669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for deleted property if property can actually be deleted.
2671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!is_dont_delete) {
2672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
26736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ cmp(r4, ip);
2674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &miss);
2675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r0, r4);
26780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ IncrementCounter(&Counters::named_load_global_stub, 1, r1, r3);
2679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
2680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
26820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ IncrementCounter(&Counters::named_load_global_stub_miss, 1, r1, r3);
2683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26905913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name,
26915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                     JSObject* receiver,
26925913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                     JSObject* holder,
26935913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                     int index) {
2694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
26966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
269725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
27026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(r0, Operand(Handle<String>(name)));
2703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss);
2706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
2710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27135913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadCallback(
27145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    String* name,
27155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    JSObject* receiver,
27165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    JSObject* holder,
27175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    AccessorInfo* callback) {
2718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
27206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
272125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
27266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(r0, Operand(Handle<String>(name)));
2727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Failure* failure = Failure::InternalError();
27303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  bool success = GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, r4,
2731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                      callback, name, &miss, &failure);
27320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!success) {
27330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    miss.Unuse();
27340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    return failure;
27350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
2736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27445913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
27455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                        JSObject* receiver,
27465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                        JSObject* holder,
27475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                        Object* value) {
2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
27506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
275125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
27566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(r0, Operand(Handle<String>(name)));
2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss);
2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
2765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27685913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
27695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                           JSObject* holder,
27705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                           String* name) {
2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
27736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
277425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
27796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(r0, Operand(Handle<String>(name)));
2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupResult lookup;
27834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  LookupPostInterceptor(holder, name, &lookup);
2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadInterceptor(receiver,
2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          holder,
2786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &lookup,
27876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                          r1,
2788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r0,
2789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r2,
2790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r3,
27913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                          r4,
2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          name,
2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &miss);
2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28015913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
28046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
280525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
28106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(r0, Operand(Handle<String>(name)));
2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateLoadArrayLength(masm(), r1, r2, &miss);
2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28215913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
28246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
282525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
28288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ IncrementCounter(&Counters::keyed_load_string_length, 1, r2, r3);
2829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the key is the cached one.
28316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(r0, Operand(Handle<String>(name)));
2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateLoadStringLength(masm(), r1, r2, r3, &miss);
2835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
28368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ DecrementCounter(&Counters::keyed_load_string_length, 1, r2, r3);
2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28445913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
2845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
28476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- r0    : key
284825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  //  -- r1    : receiver
2849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
28508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label miss;
28518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
28528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ IncrementCounter(&Counters::keyed_load_function_prototype, 1, r2, r3);
28538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
28548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Check the name hasn't changed.
28558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ cmp(r0, Operand(Handle<String>(name)));
28568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(ne, &miss);
28578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
28588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss);
28598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&miss);
28608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ DecrementCounter(&Counters::keyed_load_function_prototype, 1, r2, r3);
2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28675913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
28685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                       int index,
28695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                       Map* transition,
28705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                       String* name) {
2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
2873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r1    : key
2874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- r2    : receiver
2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ IncrementCounter(&Counters::keyed_store_field, 1, r3, r4);
2880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
2882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ cmp(r1, Operand(Handle<String>(name)));
2883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // r3 is used as scratch register. r1 and r2 keep their values if a jump to
2886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // the miss label is generated.
2887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateStoreField(masm(),
2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     object,
2889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     index,
2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     transition,
2891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                     r2, r1, r3,
2892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     &miss);
2893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ DecrementCounter(&Counters::keyed_store_field, 1, r3, r4);
2896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
2897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
2899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangMaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : argc
2908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1    : constructor
2909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp]  : last argument
2911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_stub_call;
2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use r7 for holding undefined which is used in several places below.
2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
2916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check to see whether there are any break points in the function code. If
2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // there are jump to the generic constructor stub which calls the actual
2920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code for the function thereby hitting the break points.
2921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
2922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset));
2923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, r7);
2924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &generic_stub_call);
2925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map and verify that it is in fact a map.
2928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
2931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(r2, Operand(kSmiTagMask));
2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &generic_stub_call);
2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(r2, r3, r4, MAP_TYPE);
2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &generic_stub_call);
2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cannot construct functions this way.
2938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: initial map
2941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
2942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Check(ne, "Function constructed by construct stub.");
2944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Now allocate the JSObject in new space.
2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: initial map
2950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ AllocateInNewSpace(r3,
2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        r4,
2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        r5,
2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        r6,
2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        &generic_stub_call,
295725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                        SIZE_IN_WORDS);
2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSObject, now initialize the fields. Map is set to initial
2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // map and properties and elements are set to empty fixed array.
2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: initial map
2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: object size (in words)
2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject (not tagged)
2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r5, r4);
2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
2973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the first argument. The stack contains only the
2977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // argc arguments.
2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2));
2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill all the in-object properties with undefined.
2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: first argument
2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: object size (in words)
2984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject (not tagged)
2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r5: First in-object property of JSObject (not tagged)
2986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the initialized properties with a constant value or a passed argument
2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // depending on the this.x = ...; assignment in the function.
29898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  SharedFunctionInfo* shared = function->shared();
2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (shared->IsThisPropertyAssignmentArgument(i)) {
2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Label not_passed, next;
2993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check if the argument assigned to the property is actually passed.
2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int arg_number = shared->GetThisPropertyAssignmentArgument(i);
2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(r0, Operand(arg_number));
2996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(le, &not_passed);
2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Argument passed - find it on the stack.
2998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ ldr(r2, MemOperand(r1, (arg_number + 1) * -kPointerSize));
2999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
3000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(&next);
3001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&not_passed);
3002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to undefined.
3003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&next);
3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to the constant value.
3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ mov(r2, Operand(constant));
3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the unused in-object property fields with undefined.
30148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(function->has_initial_map());
3015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = shared->this_property_assignments_count();
30168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang       i < function->initial_map()->inobject_properties();
3017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       i++) {
3018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
3019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
3022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject (not tagged)
3023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move argc to r1 and the JSObject to return to r0 and tag it.
3024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r1, r0);
3025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r4);
3026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ orr(r0, r0, Operand(kHeapObjectTag));
3027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: JSObject
3029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: argc
3030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack and return.
3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2));
3032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::constructed_objects, 1, r1, r2);
3034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::constructed_objects_stub, 1, r1, r2);
3035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
3036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic stub in case the specialized code cannot handle the
3038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // construction.
3039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_stub_call);
3040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
3041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> generic_construct_stub(code);
3042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
3043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode();
3046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
3050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
3052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
3054