stub-cache-arm.cc revision d0582a6c46733687d045e4188a1bcd0123c758a1
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 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h" 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm) 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ProbeTable(MacroAssembler* masm, 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags, 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::Table table, 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name, 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register offset) { 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference key_offset(SCTableReference::keyReference(table)); 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference value_offset(SCTableReference::valueReference(table)); 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the offset on the stack. 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(offset); 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key in the entry matches the name. 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ip, Operand(key_offset)); 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(ip, offset, LSL, 1)); 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(name, Operand(ip)); 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the code entry from the cache. 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ip, Operand(value_offset)); 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(offset, MemOperand(ip, offset, LSL, 1)); 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the flags match what we're looking for. 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(offset, FieldMemOperand(offset, Code::kFlagsOffset)); 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(offset, offset, Operand(~Code::kFlagsNotUsedInLookup)); 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(offset, Operand(flags)); 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore offset and re-load code entry from cache. 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(offset); 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ip, Operand(value_offset)); 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(offset, MemOperand(ip, offset, LSL, 1)); 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the first instruction in the code stub. 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag)); 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(offset); 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Miss: Restore offset and fall through. 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(offset); 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm, 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags, 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name, 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register extra) { 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that code is valid. The shifting code relies on the 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // entry size being 8. 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(sizeof(Entry) == 8); 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure the flags does not name a specific type. 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Code::ExtractTypeFromFlags(flags) == 0); 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that there are no register conflicts. 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(receiver)); 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(name)); 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver, Operand(kSmiTagMask)); 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the receiver and compute the hash. 108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset)); 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset)); 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(scratch, scratch, Operand(ip)); 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ eor(scratch, scratch, Operand(flags)); 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch, 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch, 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize)); 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the primary table. 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ProbeTable(masm, flags, kPrimary, name, scratch); 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Primary miss: Compute hash for secondary probe. 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(scratch, scratch, Operand(name)); 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(scratch, scratch, Operand(flags)); 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch, 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch, 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize)); 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the secondary table. 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ProbeTable(masm, flags, kSecondary, name, scratch); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Fall-through and let caller handle the miss by 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // entering the runtime system. 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register prototype) { 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global or builtins object from the current context. 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global context from the global or builtins object. 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset)); 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the function from the global context. 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index))); 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map. The global functions all have initial maps. 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the prototype from the initial map. 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load a fast property out of a holder object (src). In-object properties 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are loaded directly otherwise the property is loaded from the properties 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// fixed array. 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dst, Register src, 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, int index) { 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust for the number of properties stored in the holder. 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index -= holder->map()->inobject_properties(); 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < 0) { 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the property straight out of the holder. 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = holder->map()->instance_size() + (index * kPointerSize); 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(dst, FieldMemOperand(src, offset)); 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the offset into the properties array. 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(dst, FieldMemOperand(dst, offset)); 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver, Operand(kSmiTagMask)); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, miss_label); 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a JS array. 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, miss_label); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load length directly from the JS array. 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to check if an object is a string. If the object is 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a string, the map's instance type is left in the scratch1 register. 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm, 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* smi, 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* non_string_object) { 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver, Operand(kSmiTagMask)); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, smi); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a string. 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch2, scratch1, Operand(kIsNotStringMask)); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The cast is to resolve the overload for the argument of 0x0. 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag))); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, non_string_object); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to load the length from a string object and return the length. 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the receiver object is not a string or a wrapped string object the 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// execution continues at the miss label. The register containing the 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// receiver is potentially clobbered. 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm, 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label check_string, check_wrapper; 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_string); 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the object is a string leaving the instance type in the 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch1 register. 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateStringCheck(masm, receiver, scratch1, scratch2, 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block miss, &check_wrapper); 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load length directly from the string. 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset)); 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the object is a JSValue wrapper. 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_wrapper); 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(scratch1, Operand(JS_VALUE_TYPE)); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, miss); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Unwrap the value in place and check if the wrapped value is a string. 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(receiver, FieldMemOperand(receiver, JSValue::kValueOffset)); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&check_string); 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, scratch1); 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate StoreField code, value is passed in r0 register. 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// After executing generated code, the receiver_reg and name_reg 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// may be clobbered. 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm, 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Builtins::Name storage_extend, 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* object, 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* transition, 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver_reg, 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0 : value 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label exit; 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver_reg, Operand(kSmiTagMask)); 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, miss_label); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the receiver hasn't changed. 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(scratch, Operand(Handle<Map>(object->map()))); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, miss_label); 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform map transition for the receiver if necessary. 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The properties must be extended before we can store the value. 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We jump to a runtime call that extends the properties array. 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(Handle<Map>(transition))); 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Please note, if we implement keyed store for arm we need 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to call the Builtins::KeyedStoreIC_ExtendStorage. 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage)); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (transition != NULL) { 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the map of the object; no write barrier updating is 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // needed because the map is never in new space. 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ip, Operand(Handle<Map>(transition))); 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust for the number of properties stored in the object. Even in the 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // face of a transition we can use the old map here because the size of the 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object and the number of in-object properties is not going to change. 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index -= object->map()->inobject_properties(); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < 0) { 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property straight into the object. 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = object->map()->instance_size() + (index * kPointerSize); 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, FieldMemOperand(receiver_reg, offset)); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip updating write barrier if storing a smi. 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r0, Operand(kSmiTagMask)); 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &exit); 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pass the value being stored in the now unused name_reg. 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(name_reg, Operand(offset)); 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ RecordWrite(receiver_reg, name_reg, scratch); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Write to the properties array. 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the properties array 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, FieldMemOperand(scratch, offset)); 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip updating write barrier if storing a smi. 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r0, Operand(kSmiTagMask)); 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &exit); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ok to clobber receiver_reg and name_reg, since we return. 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(name_reg, Operand(offset)); 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ RecordWrite(scratch, name_reg, receiver_reg); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the value (register r0). 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit); 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = NULL; 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (kind == Code::LOAD_IC) { 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block code = Builtins::builtin(Builtins::LoadIC_Miss); 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(code); 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm()) 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister StubCompiler::CheckPrototypes(JSObject* object, 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register object_reg, 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register holder_reg, 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result = 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, miss); 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we've skipped any global objects, it's not enough to verify 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // that their maps haven't changed. 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (object != holder) { 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalObject* global = GlobalObject::cast(object); 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* probe = global->EnsurePropertyCell(name); 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (probe->IsFailure()) { 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block set_failure(Failure::cast(probe)); 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(cell->value()->IsTheHole()); 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(scratch, Operand(Handle<Object>(cell))); 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(scratch, 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(scratch, ip); 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, miss); 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object = JSObject::cast(object->GetPrototype()); 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the register containin the holder. 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadField(JSObject* object, 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver, Operand(kSmiTagMask)); 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, miss); 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss); 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), r0, reg, holder, index); 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadConstant(JSObject* object, 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* value, 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver, Operand(kSmiTagMask)); 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, miss); 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss); 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the constant value. 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(Handle<Object>(value))); 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadCallback(JSObject* object, 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AccessorInfo* callback, 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver, Operand(kSmiTagMask)); 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, miss); 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss); 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the arguments on the JS stack of the caller. 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(receiver); // receiver 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(reg); // holder 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(reg, FieldMemOperand(ip, AccessorInfo::kDataOffset)); 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(reg); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(name_reg); // name 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference load_callback_property = 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ TailCallRuntime(load_callback_property, 5, 1); 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadInterceptor(JSObject* object, 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult* lookup, 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver, Operand(kSmiTagMask)); 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, miss); 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss); 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the arguments on the JS stack of the caller. 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(receiver); // receiver 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(reg); // holder 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(name_reg); // name 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InterceptorInfo* interceptor = holder->GetNamedInterceptor(); 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!Heap::InNewSpace(interceptor)); 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(scratch1, Operand(Handle<Object>(interceptor))); 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(scratch1); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(scratch2, FieldMemOperand(scratch1, InterceptorInfo::kDataOffset)); 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(scratch2); 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference load_ic_property = 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ TailCallRuntime(load_ic_property, 5, 1); 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StubCompiler::CompileLazyCompile(Code::Flags flags) { 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1: function 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr: return address 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter an internal frame. 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterInternalFrame(); 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preserve the function. 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the function on the stack as the argument to the runtime function. 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CallRuntime(Runtime::kLazyCompile, 1); 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the entry point. 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore saved function. 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(r1); 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tear down temporary frame. 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveInternalFrame(); 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do a tail-call of the compiled function. 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(r2); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCodeWithFlags(flags, "LazyCompileStub"); 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallStubCompiler::CompileCallField(Object* object, 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr: return address 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack into r0. 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r0, Operand(kSmiTagMask)); 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do the right check and compute the holder register. 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(JSObject::cast(object), r0, holder, r3, r2, name, &miss); 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), r1, reg, holder, index); 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r1, Operand(kSmiTagMask)); 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map. 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r3, MemOperand(sp, argc * kPointerSize)); 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(r1, arguments(), JUMP_FUNCTION); 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic = ComputeCallMiss(arguments().immediate()); 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallStubCompiler::CompileCallConstant(Object* object, 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSFunction* function, 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckType check) { 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr: return address 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check != NUMBER_CHECK) { 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r1, Operand(kSmiTagMask)); 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that it's okay not to patch the on stack receiver 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // unless we're doing a receiver map check. 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (check) { 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RECEIVER_MAP_CHECK: 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(JSObject::cast(object), r1, holder, r3, r2, name, &miss); 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r3, MemOperand(sp, argc * kPointerSize)); 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case STRING_CHECK: 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a two-byte string or a symbol. 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r1, r2, r2, FIRST_NONSTRING_TYPE); 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(hs, &miss); 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps starting from the prototype haven't changed. 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadGlobalFunctionPrototype(masm(), 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::STRING_FUNCTION_INDEX, 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2); 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3, 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, name, &miss); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case NUMBER_CHECK: { 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fast; 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a smi or a heap number. 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r1, Operand(kSmiTagMask)); 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &fast); 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fast); 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps starting from the prototype haven't changed. 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadGlobalFunctionPrototype(masm(), 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::NUMBER_FUNCTION_INDEX, 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2); 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3, 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, name, &miss); 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case BOOLEAN_CHECK: { 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fast; 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a boolean. 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(ip, Heap::kTrueValueRootIndex); 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r1, ip); 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &fast); 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(ip, Heap::kFalseValueRootIndex); 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r1, ip); 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fast); 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps starting from the prototype haven't changed. 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadGlobalFunctionPrototype(masm(), 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::BOOLEAN_FUNCTION_INDEX, 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2); 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3, 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, name, &miss); 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case JSARRAY_HAS_FAST_ELEMENTS_CHECK: 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(JSObject::cast(object), r1, holder, r3, r2, name, &miss); 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure object->HasFastElements(). 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the elements array of the object. 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset)); 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is in fast mode (not dictionary). 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, ip); 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the function and setup the context. 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r1, Operand(Handle<JSFunction>(function))); 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the cached code (tail call). 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(function->is_compiled()); 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code(function->code()); 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(function->shared()->formal_parameter_count()); 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeCode(code, expected, arguments(), 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::CODE_TARGET, JUMP_FUNCTION); 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic = ComputeCallMiss(arguments().immediate()); 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* function_name = NULL; 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (function->shared()->name()->IsString()) { 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block function_name = String::cast(function->shared()->name()); 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, function_name); 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallStubCompiler::CompileCallInterceptor(Object* object, 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr: return address 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1224669): Implement. 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic = ComputeCallMiss(arguments().immediate()); 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallStubCompiler::CompileCallGlobal(JSObject* object, 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalObject* holder, 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSGlobalPropertyCell* cell, 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSFunction* function, 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr: return address 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments. 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the object is the holder then we know that it's a global 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object which can only happen for contextual calls. In this case, 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the receiver cannot be a smi. 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object != holder) { 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r0, Operand(kSmiTagMask)); 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(object, r0, holder, r3, r2, name, &miss); 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value from the cell. 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the cell contains the same function. 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r1, Operand(Handle<JSFunction>(function))); 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r3, MemOperand(sp, argc * kPointerSize)); 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup the context (function already in r1). 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the cached code (tail call). 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::call_global_inline, 1, r2, r3); 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(function->is_compiled()); 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code(function->code()); 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(function->shared()->formal_parameter_count()); 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeCode(code, expected, arguments(), 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::CODE_TARGET, JUMP_FUNCTION); 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic = ComputeCallMiss(arguments().immediate()); 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreField(JSObject* object, 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* transition, 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : receiver 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, MemOperand(sp, 0 * kPointerSize)); 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // name register might be clobbered. 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateStoreField(masm(), 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Builtins::StoreIC_ExtendStorage, 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object, 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index, 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block transition, 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, r2, r1, 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(Handle<String>(name))); // restore name 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AccessorInfo* callback, 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : receiver 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the object from the stack. 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, MemOperand(sp, 0 * kPointerSize)); 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r3, Operand(kSmiTagMask)); 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset)); 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r1, Operand(Handle<Map>(object->map()))); 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(r3, r1, &miss); 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(sp)); // receiver 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r2); // name 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); // value 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_callback_property = 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(IC_Utility(IC::kStoreCallbackProperty)); 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ TailCallRuntime(store_callback_property, 4, 1); 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(Handle<String>(name))); // restore name 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : receiver 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the object from the stack. 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, MemOperand(sp, 0 * kPointerSize)); 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r3, Operand(kSmiTagMask)); 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset)); 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r1, Operand(Handle<Map>(receiver->map()))); 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (receiver->IsJSGlobalProxy()) { 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(r3, r1, &miss); 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(sp)); // receiver 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r2); // name 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); // value 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_ic_property = 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(IC_Utility(IC::kStoreInterceptorProperty)); 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ TailCallRuntime(store_ic_property, 3, 1); 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(Handle<String>(name))); // restore name 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSGlobalPropertyCell* cell, 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : receiver 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r3, Operand(Handle<Map>(object->map()))); 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the value in the cell. 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(Handle<JSGlobalPropertyCell>(cell))); 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::named_store_global_inline, 1, r1, r3); 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::named_store_global_inline_miss, 1, r1, r3); 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadField(JSObject* object, 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : receiver 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, 0)); 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadField(object, holder, r0, r3, r1, index, name, &miss); 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadCallback(JSObject* object, 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AccessorInfo* callback, 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : receiver 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, 0)); 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadCallback(object, holder, r0, r2, r3, r1, callback, name, &miss); 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadConstant(JSObject* object, 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* value, 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : receiver 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, 0)); 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadConstant(object, holder, r0, r3, r1, value, name, &miss); 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : receiver 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, 0)); 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult lookup; 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block holder->LocalLookupRealNamedProperty(name, &lookup); 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadInterceptor(object, 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block holder, 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &lookup, 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r0, 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block name, 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object, 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalObject* holder, 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSGlobalPropertyCell* cell, 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_dont_delete) { 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : receiver 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the object is the holder then we know that it's a global 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object which can only happen for contextual calls. In this case, 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the receiver cannot be a smi. 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object != holder) { 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r1, Operand(kSmiTagMask)); 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(object, r1, holder, r3, r0, name, &miss); 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value from the cell. 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for deleted property if property can actually be deleted. 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_dont_delete) { 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, ip); 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::named_load_global_inline, 1, r1, r3); 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::named_load_global_inline_miss, 1, r1, r3); 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadField(String* name, 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* receiver, 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index) { 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[0] : key 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[4] : receiver 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(sp, 0)); 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, kPointerSize)); 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(Handle<String>(name))); 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadField(receiver, holder, r0, r3, r1, index, name, &miss); 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadCallback(String* name, 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* receiver, 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AccessorInfo* callback) { 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[0] : key 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[4] : receiver 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(sp, 0)); 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, kPointerSize)); 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(Handle<String>(name))); 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadCallback(receiver, holder, r0, r2, r3, r1, callback, name, &miss); 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* receiver, 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* value) { 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[0] : key 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[4] : receiver 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the key is the cached one 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(sp, 0)); 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, kPointerSize)); 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(Handle<String>(name))); 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadConstant(receiver, holder, r0, r3, r1, value, name, &miss); 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[0] : key 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[4] : receiver 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the key is the cached one 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(sp, 0)); 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, kPointerSize)); 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(Handle<String>(name))); 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult lookup; 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block holder->LocalLookupRealNamedProperty(name, &lookup); 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadInterceptor(receiver, 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block holder, 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &lookup, 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r0, 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block name, 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[0] : key 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[4] : receiver 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the key is the cached one 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(sp, 0)); 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, kPointerSize)); 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(Handle<String>(name))); 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadArrayLength(masm(), r0, r3, &miss); 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[0] : key 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[4] : receiver 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3); 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(sp)); 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(Handle<String>(name))); 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadStringLength2(masm(), r0, r1, r3, &miss); 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3); 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// TODO(1224671): implement the fast case. 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[0] : key 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[4] : receiver 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* transition, 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : receiver 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3); 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(Handle<String>(name))); 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load receiver from the stack. 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, MemOperand(sp)); 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1 is used as scratch register, r3 and r2 might be clobbered. 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateStoreField(masm(), 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Builtins::StoreIC_ExtendStorage, 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object, 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index, 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block transition, 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, r2, r1, 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3); 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(Handle<String>(name))); // restore name register. 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* ConstructStubCompiler::CompileConstructStub( 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SharedFunctionInfo* shared) { 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : argc 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : constructor 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : last argument 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_stub_call; 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use r7 for holding undefined which is used in several places below. 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check to see whether there are any break points in the function code. If 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // there are jump to the generic constructor stub which calls the actual 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code for the function thereby hitting the break points. 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset)); 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, r7); 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &generic_stub_call); 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map and verify that it is in fact a map. 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, Operand(kSmiTagMask)); 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &generic_stub_call); 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r4, MAP_TYPE); 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &generic_stub_call); 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cannot construct functions this way. 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Check(ne, "Function constructed by construct stub."); 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Now allocate the JSObject in new space. 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ AllocateInNewSpace(r3, 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r4, 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r5, 1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r6, 1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &generic_stub_call, 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NO_ALLOCATION_FLAGS); 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSObject, now initialize the fields. Map is set to initial 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // map and properties and elements are set to empty fixed array. 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: object size (in words) 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r5, r4); 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the first argument. The stack contains only the 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // argc arguments. 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2)); 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill all the in-object properties with undefined. 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: first argument 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: object size (in words) 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: First in-object property of JSObject (not tagged) 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the initialized properties with a constant value or a passed argument 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // depending on the this.x = ...; assignment in the function. 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < shared->this_property_assignments_count(); i++) { 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shared->IsThisPropertyAssignmentArgument(i)) { 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label not_passed, next; 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the argument assigned to the property is actually passed. 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int arg_number = shared->GetThisPropertyAssignmentArgument(i); 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(arg_number)); 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(le, ¬_passed); 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Argument passed - find it on the stack. 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(r1, (arg_number + 1) * -kPointerSize)); 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&next); 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(¬_passed); 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to undefined. 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&next); 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to the constant value. 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i)); 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(constant)); 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the unused in-object property fields with undefined. 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = shared->this_property_assignments_count(); 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i < shared->CalculateInObjectProperties(); 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i++) { 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move argc to r1 and the JSObject to return to r0 and tag it. 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r1, r0); 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, r4); 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ orr(r0, r0, Operand(kHeapObjectTag)); 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: JSObject 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: argc 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments and receiver from the stack and return. 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2)); 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::constructed_objects, 1, r1, r2); 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::constructed_objects_stub, 1, r1, r2); 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic stub in case the specialized code cannot handle the 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // construction. 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_stub_call); 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> generic_construct_stub(code); 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(); 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1488