ic-arm.cc revision e0cee9b3ed82e2391fd85d118aeaa4ea361c687d
17ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Copyright 2006-2008 the V8 project authors. All rights reserved. 27ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Redistribution and use in source and binary forms, with or without 37ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// modification, are permitted provided that the following conditions are 47ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// met: 57ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// 67ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// * Redistributions of source code must retain the above copyright 77ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// notice, this list of conditions and the following disclaimer. 87ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// * Redistributions in binary form must reproduce the above 97ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// copyright notice, this list of conditions and the following 107ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// disclaimer in the documentation and/or other materials provided 117ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// with the distribution. 127ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// * Neither the name of Google Inc. nor the names of its 137ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// contributors may be used to endorse or promote products derived 147ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// from this software without specific prior written permission. 157ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// 167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 287ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#include "v8.h" 297ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#if defined(V8_TARGET_ARCH_ARM) 317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#include "assembler-arm.h" 337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#include "code-stubs.h" 347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#include "codegen-inl.h" 357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#include "disasm.h" 367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#include "ic-inl.h" 377ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#include "runtime.h" 387ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#include "stub-cache.h" 397ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 407ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmannamespace v8 { 417ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmannamespace internal { 427ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 437ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 447ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// ---------------------------------------------------------------------------- 4557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// Static IC stub generators. 4657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// 477ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 487ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#define __ ACCESS_MASM(masm) 497ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 507ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 517ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanstatic void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, 527ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register type, 537ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Label* global_object) { 547ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Register usage: 557ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // type: holds the receiver instance type on entry. 567ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ cmp(type, Operand(JS_GLOBAL_OBJECT_TYPE)); 577ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, global_object); 587ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE)); 597ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, global_object); 60190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE)); 617ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, global_object); 62190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer} 63190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 64190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 65190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// Generated code falls through if the receiver is a regular non-global 66190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// JS object with slow properties and no interceptors. 67190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramerstatic void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm, 68190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Register receiver, 6957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register elements, 7057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register t0, 7157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register t1, 7257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Label* miss) { 7357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Register usage: 7457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // receiver: holds the receiver on entry and is unchanged. 7557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // elements: holds the property dictionary on fall through. 767ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Scratch registers: 777ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // t0: used to holds the receiver map. 787ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // t1: used to holds the receiver instance type, receiver bit mask and 79e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // elements map. 80e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer 8157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Check that the receiver isn't a smi. 82e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ tst(receiver, Operand(kSmiTagMask)); 83e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ b(eq, miss); 84e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer 85e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // Check that the receiver is a valid JS object. 86e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ CompareObjectType(receiver, t0, t1, FIRST_JS_OBJECT_TYPE); 87190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ b(lt, miss); 88190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 89190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // If this assert fails, we have to check upper bound too. 9057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 91e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer 927ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateGlobalInstanceTypeCheck(masm, t1, miss); 937ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 947ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check that the global object does not require access checks. 957ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldrb(t1, FieldMemOperand(t0, Map::kBitFieldOffset)); 967ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ tst(t1, Operand((1 << Map::kIsAccessCheckNeeded) | 977ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman (1 << Map::kHasNamedInterceptor))); 987ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(ne, miss); 997ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 100e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 1017ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(t1, FieldMemOperand(elements, HeapObject::kMapOffset)); 102e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 103e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ cmp(t1, ip); 104e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ b(ne, miss); 105e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer} 106e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer 107e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer 108e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Probe the string dictionary in the |elements| register. Jump to the 109e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// |done| label if a property with the given name is found. Jump to 110e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// the |miss| label otherwise. 111e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerstatic void GenerateStringDictionaryProbes(MacroAssembler* masm, 112e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer Label* miss, 11357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Label* done, 1147ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register elements, 1157ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register name, 1167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register scratch1, 117190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Register scratch2) { 118190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Assert that name contains a string. 11957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (FLAG_debug_code) __ AbortIfNotString(name); 1207ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 1217ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Compute the capacity mask. 1227ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman const int kCapacityOffset = StringDictionary::kHeaderSize + 1237ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman StringDictionary::kCapacityIndex * kPointerSize; 1247ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset)); 1257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ mov(scratch1, Operand(scratch1, ASR, kSmiTagSize)); // convert smi to int 1267ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ sub(scratch1, scratch1, Operand(1)); 1277ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 1287ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman const int kElementsStartOffset = StringDictionary::kHeaderSize + 1297ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman StringDictionary::kElementsStartIndex * kPointerSize; 1307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 1317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Generate an unrolled loop that performs a few probes before 1327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // giving up. Measurements done on Gmail indicate that 2 probes 1337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // cover ~93% of loads from dictionaries. 1347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman static const int kProbes = 4; 1357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman for (int i = 0; i < kProbes; i++) { 1367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Compute the masked index: (hash + i + i * i) & mask. 1377ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(scratch2, FieldMemOperand(name, String::kHashFieldOffset)); 1387ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman if (i > 0) { 1397ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Add the probe offset (i + i * i) left shifted to avoid right shifting 1407ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // the hash in a separate instruction. The value hash + i + i * i is right 1417ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // shifted in the following and instruction. 1427ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman ASSERT(StringDictionary::GetProbeOffset(i) < 1437ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 1 << (32 - String::kHashFieldOffset)); 1447ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ add(scratch2, scratch2, Operand( 1457ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman StringDictionary::GetProbeOffset(i) << String::kHashShift)); 14657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } 14757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ and_(scratch2, scratch1, Operand(scratch2, LSR, String::kHashShift)); 14857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 14957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Scale the index by multiplying by the element size. 1507ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman ASSERT(StringDictionary::kEntrySize == 3); 1517ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // scratch2 = scratch2 * 3. 1527ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ add(scratch2, scratch2, Operand(scratch2, LSL, 1)); 1537ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 1547ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check if the key is identical to the name. 1557ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ add(scratch2, elements, Operand(scratch2, LSL, 2)); 1567ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset)); 1577ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ cmp(name, Operand(ip)); 1587ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman if (i != kProbes - 1) { 1597ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, done); 1607ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman } else { 1617ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(ne, miss); 1627ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman } 1637ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman } 1647ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman} 1657ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 1667ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 1677ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Helper function used from LoadIC/CallIC GenerateNormal. 1687ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// 1697ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// elements: Property dictionary. It is not clobbered if a jump to the miss 1707ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// label is done. 1717ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// name: Property name. It is not clobbered if a jump to the miss label is 172190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// done 1737ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// result: Register for the result. It is only updated if a jump to the miss 1747ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// label is not done. Can be the same as elements or name clobbering 175190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// one of these in the case of not jumping to the miss label. 176190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// The two scratch registers need to be different from elements, name and 177190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// result. 178190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// The generated code assumes that the receiver has slow properties, 179190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// is not a global object and does not have interceptors. 180190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramerstatic void GenerateDictionaryLoad(MacroAssembler* masm, 18157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Label* miss, 18257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register elements, 1837ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register name, 184e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer Register result, 185e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer Register scratch1, 18657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register scratch2) { 187e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // Main use of the scratch registers. 188e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // scratch1: Used as temporary and to hold the capacity of the property 189e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // dictionary. 1907ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // scratch2: Used as temporary. 1917ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Label done; 1927ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 1937ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Probe the dictionary. 1947ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateStringDictionaryProbes(masm, 1957ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman miss, 1967ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman &done, 1977ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman elements, 1987ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman name, 1997ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman scratch1, 200e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer scratch2); 201190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 202e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // If probing finds an entry check that the value is a normal 203190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // property. 204e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ bind(&done); // scratch2 == elements + 4 * index 205190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer const int kElementsStartOffset = StringDictionary::kHeaderSize + 206190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer StringDictionary::kElementsStartIndex * kPointerSize; 207190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 208190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); 209190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ tst(scratch1, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize)); 210190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ b(ne, miss); 211190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 2127ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Get the value at the masked, scaled index and return. 213e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ ldr(result, 2147ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); 215e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer} 2167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 217e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer 2187ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Helper function used from StoreIC::GenerateNormal. 219e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// 22057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// elements: Property dictionary. It is not clobbered if a jump to the miss 22157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// label is done. 222df40664a63a91a1ab4b40c7f2d356cf255071d56Edward O'Callaghan// name: Property name. It is not clobbered if a jump to the miss label is 223df40664a63a91a1ab4b40c7f2d356cf255071d56Edward O'Callaghan// done 224190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// value: The value to store. 2257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// The two scratch registers need to be different from elements, name and 226190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// result. 22757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// The generated code assumes that the receiver has slow properties, 2287ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// is not a global object and does not have interceptors. 229e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerstatic void GenerateDictionaryStore(MacroAssembler* masm, 230e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer Label* miss, 231e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer Register elements, 232e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer Register name, 233e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer Register value, 234190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Register scratch1, 235190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Register scratch2) { 23657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Main use of the scratch registers. 237190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // scratch1: Used as temporary and to hold the capacity of the property 238190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // dictionary. 239e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // scratch2: Used as temporary. 240e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer Label done; 241190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 242190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Probe the dictionary. 243190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer GenerateStringDictionaryProbes(masm, 244190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer miss, 245190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer &done, 246190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer elements, 247190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer name, 248190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer scratch1, 249190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer scratch2); 250190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 251190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // If probing finds an entry in the dictionary check that the value 252e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // is a normal property that is not read only. 253e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ bind(&done); // scratch2 == elements + 4 * index 254e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer const int kElementsStartOffset = StringDictionary::kHeaderSize + 255e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer StringDictionary::kElementsStartIndex * kPointerSize; 256e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 257e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer const int kTypeAndReadOnlyMask 258190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer = (PropertyDetails::TypeField::mask() | 25957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; 2607ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); 26157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ tst(scratch1, Operand(kTypeAndReadOnlyMask)); 26257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ b(ne, miss); 26357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 264190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Store the value at the masked, scaled index and return. 265190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer const int kValueOffset = kElementsStartOffset + kPointerSize; 266190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ add(scratch2, scratch2, Operand(kValueOffset - kHeapObjectTag)); 2677ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ str(value, MemOperand(scratch2)); 268190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 2697ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Update the write barrier. Make sure not to clobber the value. 2707ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ mov(scratch1, value); 2717ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ RecordWrite(elements, scratch2, scratch1); 27257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 27357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 27457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 27557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramerstatic void GenerateNumberDictionaryLoad(MacroAssembler* masm, 27657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Label* miss, 27757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register elements, 27857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register key, 27957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register result, 28057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register t0, 28157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register t1, 282e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer Register t2) { 283e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // Register use: 28457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // 28557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // elements - holds the slow-case elements of the receiver on entry. 2867ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Unchanged unless 'result' is the same register. 287190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // 28857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // key - holds the smi key on entry. 289e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // Unchanged unless 'result' is the same register. 29057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // 29157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // result - holds the result on exit if the load succeeded. 29257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Allowed to be the same as 'key' or 'result'. 293e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // Unchanged on bailout so 'key' or 'result' can be used 29457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // in further computation. 29557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // 29657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Scratch registers: 29757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // 2987ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // t0 - holds the untagged key on entry and holds the hash once computed. 2997ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // 3007ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // t1 - used to hold the capacity mask of the dictionary 3017ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // 3027ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // t2 - used for the index into the dictionary. 3037ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Label done; 3047ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 3057ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Compute the hash code from the untagged key. This must be kept in sync 3067ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // with ComputeIntegerHash in utils.h. 3077ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // 3087ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // hash = ~hash + (hash << 15); 3097ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ mvn(t1, Operand(t0)); 3107ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ add(t0, t1, Operand(t0, LSL, 15)); 3117ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // hash = hash ^ (hash >> 12); 3127ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ eor(t0, t0, Operand(t0, LSR, 12)); 313e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // hash = hash + (hash << 2); 314e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ add(t0, t0, Operand(t0, LSL, 2)); 3157ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // hash = hash ^ (hash >> 4); 31621aa347c2816aa8fc635ad05c5ab786234b32c7eChris Lattner __ eor(t0, t0, Operand(t0, LSR, 4)); 31757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // hash = hash * 2057; 3187ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ mov(t1, Operand(2057)); 3197ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ mul(t0, t0, t1); 3207ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // hash = hash ^ (hash >> 16); 3217ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ eor(t0, t0, Operand(t0, LSR, 16)); 3227ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 3237ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Compute the capacity mask. 324e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ ldr(t1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset)); 325e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ mov(t1, Operand(t1, ASR, kSmiTagSize)); // convert smi to int 3267ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ sub(t1, t1, Operand(1)); 3277ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 3287ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Generate an unrolled loop that performs a few probes before giving up. 3297ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman static const int kProbes = 4; 3307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman for (int i = 0; i < kProbes; i++) { 3317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Use t2 for index calculations and keep the hash intact in t0. 3327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ mov(t2, t0); 3337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Compute the masked index: (hash + i + i * i) & mask. 3347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman if (i > 0) { 3357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ add(t2, t2, Operand(NumberDictionary::GetProbeOffset(i))); 3367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman } 3377ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ and_(t2, t2, Operand(t1)); 3387ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 33957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Scale the index by multiplying by the element size. 3407ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman ASSERT(NumberDictionary::kEntrySize == 3); 3417ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3 34257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 34357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Check if the key is identical to the name. 3447ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ add(t2, elements, Operand(t2, LSL, kPointerSizeLog2)); 3457ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(ip, FieldMemOperand(t2, NumberDictionary::kElementsStartOffset)); 3467ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ cmp(key, Operand(ip)); 3477ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman if (i != kProbes - 1) { 3487ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, &done); 34957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } else { 35057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ b(ne, miss); 35157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } 35257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } 35357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 35457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ bind(&done); 3557ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check that the value is a normal property. 35657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // t2: elements + (index * kPointerSize) 35757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer const int kDetailsOffset = 35857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer NumberDictionary::kElementsStartOffset + 2 * kPointerSize; 3597ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(t1, FieldMemOperand(t2, kDetailsOffset)); 3607ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::mask()))); 3617ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(ne, miss); 36257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 3637ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Get the value at the masked, scaled index and return. 3647ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman const int kValueOffset = 3657ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman NumberDictionary::kElementsStartOffset + kPointerSize; 3667ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(result, FieldMemOperand(t2, kValueOffset)); 3677ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman} 3687ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 36957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 37057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramervoid LoadIC::GenerateArrayLength(MacroAssembler* masm) { 37157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ----------- S t a t e ------------- 37257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r2 : name 37357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- lr : return address 37457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r0 : receiver 37557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- sp[0] : receiver 3767ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------------------------------- 37757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Label miss; 37857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 37957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer StubCompiler::GenerateLoadArrayLength(masm, r0, r3, &miss); 38057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ bind(&miss); 38157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 382e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer} 3837ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 3847ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 385190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramervoid LoadIC::GenerateStringLength(MacroAssembler* masm, bool support_wrappers) { 386190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // ----------- S t a t e ------------- 387190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- r2 : name 3887ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- lr : return address 389190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- r0 : receiver 390190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- sp[0] : receiver 391190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // ----------------------------------- 392190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Label miss; 393190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 394190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer StubCompiler::GenerateLoadStringLength(masm, r0, r1, r3, &miss, 395190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer support_wrappers); 3967ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Cache miss: Jump to runtime. 3977ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ bind(&miss); 39857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 39957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 40057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 40157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 40257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramervoid LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { 40357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ----------- S t a t e ------------- 40457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r2 : name 40557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- lr : return address 40657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r0 : receiver 407190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- sp[0] : receiver 4087ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------------------------------- 409190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Label miss; 41057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 411190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer StubCompiler::GenerateLoadFunctionPrototype(masm, r0, r1, r3, &miss); 412190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ bind(&miss); 4137ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 4147ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman} 4157ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 4167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 4177ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Checks the receiver for special cases (value type, slow case bits). 418190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// Falls through for regular JS object. 419190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramerstatic void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, 420190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Register receiver, 421190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Register map, 422190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Register scratch, 423190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer int interceptor_bit, 424190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Label* slow) { 425190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Check that the object isn't a smi. 426190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ JumpIfSmi(receiver, slow); 427190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Get the map of the receiver. 428190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 429190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Check bit field. 430190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset)); 431190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ tst(scratch, 432190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Operand((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); 433190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ b(ne, slow); 434190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Check that the object is some kind of JS object EXCEPT JS Value type. 435190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // In the case that the object is a value-wrapper object, 436190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // we enter the runtime system to make sure that indexing into string 437190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // objects work as intended. 438190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 439190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); 440190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ cmp(scratch, Operand(JS_OBJECT_TYPE)); 441190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ b(lt, slow); 442190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer} 443190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 444190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 445190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// Loads an indexed element from a fast case array. 446190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// If not_fast_array is NULL, doesn't perform the elements map check. 447190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramerstatic void GenerateFastArrayLoad(MacroAssembler* masm, 4487ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register receiver, 449190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Register key, 450190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Register elements, 4517ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register scratch1, 45257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register scratch2, 453190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Register result, 454190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Label* not_fast_array, 455190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Label* out_of_range) { 456190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Register use: 4577ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // 45857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // receiver - holds the receiver on entry. 459190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Unchanged unless 'result' is the same register. 460190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // 4617ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // key - holds the smi key on entry. 4627ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Unchanged unless 'result' is the same register. 4637ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // 4647ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // elements - holds the elements of the receiver on exit. 4657ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // 4667ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // result - holds the result on exit if the load succeeded. 4677ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Allowed to be the the same as 'receiver' or 'key'. 4687ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Unchanged on bailout so 'receiver' and 'key' can be safely 4697ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // used by further computation. 470e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // 4717ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Scratch registers: 4727ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // 4737ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // scratch1 - used to hold elements map and elements length. 474e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // Holds the elements map if not_fast_array branch is taken. 4757ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // 4767ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // scratch2 - used to hold the loaded value. 4777ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 47857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 47957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (not_fast_array != NULL) { 48057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Check that the object is in fast mode and writable. 48157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset)); 48257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 48357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ cmp(scratch1, ip); 4847ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(ne, not_fast_array); 48557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } else { 48657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ AssertFastElements(elements); 48757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } 48857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Check that the key (index) is within bounds. 48957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset)); 49057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ cmp(key, Operand(scratch1)); 491e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ b(hs, out_of_range); 492190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Fast case: Do the load. 493e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 4947ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // The key is a smi. 49557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 49657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ ldr(scratch2, 49757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer MemOperand(scratch1, key, LSL, kPointerSizeLog2 - kSmiTagSize)); 498e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 4997ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ cmp(scratch2, ip); 5007ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // In case the loaded value is the_hole we have to consult GetProperty 5017ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // to ensure the prototype chain is searched. 50257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ b(eq, out_of_range); 50357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ mov(result, scratch2); 50457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 50557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 506e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer 507e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Checks whether a key is an array index string or a symbol string. 50857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// Falls through if a key is a symbol. 5097ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanstatic void GenerateKeyStringCheck(MacroAssembler* masm, 5107ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register key, 51157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register map, 51257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register hash, 51357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Label* index_string, 51457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Label* not_symbol) { 515e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // The key is not a smi. 51657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Is it a string? 5177ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ CompareObjectType(key, map, hash, FIRST_NONSTRING_TYPE); 5187ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(ge, not_symbol); 519e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer 52057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Is the string an array index, with cached numeric value? 5217ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset)); 5227ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ tst(hash, Operand(String::kContainsCachedArrayIndexMask)); 5237ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, index_string); 5247ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 5257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Is the string a symbol? 5267ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // map: key map 5277ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); 5287ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman ASSERT(kSymbolTag != 0); 5297ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ tst(hash, Operand(kIsSymbolMask)); 5307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, not_symbol); 5317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman} 5327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 5337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 5347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Defined in ic.cc. 5357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha BrukmanObject* CallIC_Miss(Arguments args); 5367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 5377ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// The generated code does not accept smi keys. 538190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// The generated code falls through if both probes miss. 5397ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanstatic void GenerateMonomorphicCacheProbe(MacroAssembler* masm, 5407ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman int argc, 5417ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Code::Kind kind) { 5427ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------- S t a t e ------------- 5437ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r1 : receiver 5447ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r2 : name 5457ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------------------------------- 546190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Label number, non_number, non_string, boolean, probe, miss; 547190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 548190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Probe the stub cache. 5497ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Code::Flags flags = Code::ComputeFlags(kind, 5507ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman NOT_IN_LOOP, 5517ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman MONOMORPHIC, 5527ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Code::kNoExtraICState, 5537ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman NORMAL, 5547ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman argc); 55557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer StubCache::GenerateProbe(masm, flags, r1, r2, r3, r4, r5); 55657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 55757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // If the stub cache probing failed, the receiver might be a value. 55857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // For value objects, we use the map of the prototype objects for 55957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // the corresponding JSValue for the cache and that is what we need 56057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // to probe. 5617ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // 5627ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check for number. 56357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ tst(r1, Operand(kSmiTagMask)); 56457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ b(eq, &number); 5657ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ CompareObjectType(r1, r3, r3, HEAP_NUMBER_TYPE); 5667ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(ne, &non_number); 5677ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ bind(&number); 5687ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman StubCompiler::GenerateLoadGlobalFunctionPrototype( 5697ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman masm, Context::NUMBER_FUNCTION_INDEX, r1); 5707ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(&probe); 5717ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 5727ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check for string. 5737ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ bind(&non_number); 5747ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ cmp(r3, Operand(FIRST_NONSTRING_TYPE)); 5757ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(hs, &non_string); 5767ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman StubCompiler::GenerateLoadGlobalFunctionPrototype( 577190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer masm, Context::STRING_FUNCTION_INDEX, r1); 578190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ b(&probe); 579190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 580190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Check for boolean. 581190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ bind(&non_string); 582190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ LoadRoot(ip, Heap::kTrueValueRootIndex); 583190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ cmp(r1, ip); 584190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ b(eq, &boolean); 585190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ LoadRoot(ip, Heap::kFalseValueRootIndex); 586190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ cmp(r1, ip); 587190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ b(ne, &miss); 588190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ bind(&boolean); 589190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer StubCompiler::GenerateLoadGlobalFunctionPrototype( 590190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer masm, Context::BOOLEAN_FUNCTION_INDEX, r1); 591190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 592190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Probe the stub cache for the value object. 59357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ bind(&probe); 59457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer StubCache::GenerateProbe(masm, flags, r1, r2, r3, r4, r5); 59557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 59657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ bind(&miss); 59757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 59857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 59957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 60057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramerstatic void GenerateFunctionTailCall(MacroAssembler* masm, 60157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer int argc, 60257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Label* miss, 60357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Register scratch) { 60457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // r1: function 60557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 60657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Check that the value isn't a smi. 6077ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ tst(r1, Operand(kSmiTagMask)); 6087ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, miss); 6097ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6107ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check that the value is a JSFunction. 6117ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ CompareObjectType(r1, scratch, scratch, JS_FUNCTION_TYPE); 6127ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(ne, miss); 6137ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6147ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Invoke the function. 6157ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman ParameterCount actual(argc); 6167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ InvokeFunction(r1, actual, JUMP_FUNCTION); 617190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer} 618190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 61957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 620190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramerstatic void GenerateCallNormal(MacroAssembler* masm, int argc) { 6217ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------- S t a t e ------------- 6227ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r2 : name 6237ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- lr : return address 6247ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------------------------------- 6257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Label miss; 6267ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6277ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Get the receiver of the function from the stack into r1. 62857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 62957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 6307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateStringDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss); 6317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // r0: elements 6337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Search the dictionary - put result in register r1. 6347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateDictionaryLoad(masm, &miss, r0, r2, r1, r3, r4); 6357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateFunctionTailCall(masm, argc, &miss, r4); 6377ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6387ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ bind(&miss); 6397ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman} 6407ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6417ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6427ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanstatic void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { 6437ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------- S t a t e ------------- 6447ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r2 : name 645190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- lr : return address 6467ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------------------------------- 6477ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6487ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman if (id == IC::kCallIC_Miss) { 6497ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ IncrementCounter(&Counters::call_miss, 1, r3, r4); 6507ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman } else { 6517ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ IncrementCounter(&Counters::keyed_call_miss, 1, r3, r4); 6527ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman } 6537ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6547ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Get the receiver of the function from the stack. 6557ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(r3, MemOperand(sp, argc * kPointerSize)); 6567ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6577ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ EnterInternalFrame(); 6587ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 65957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Push the receiver and the name of the function. 6607ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ Push(r3, r2); 66157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 6627ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Call the entry. 66357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ mov(r0, Operand(2)); 66457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ mov(r1, Operand(ExternalReference(IC_Utility(id)))); 66557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 66657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer CEntryStub stub(1); 6677ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ CallStub(&stub); 6687ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6697ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Move result to r1 and leave the internal frame. 6707ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ mov(r1, Operand(r0)); 6717ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ LeaveInternalFrame(); 6727ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6737ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check if the receiver is a global object of some sort. 6747ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // This can happen only for regular CallIC but not KeyedCallIC. 6757ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman if (id == IC::kCallIC_Miss) { 6767ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Label invoke, global; 6777ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(r2, MemOperand(sp, argc * kPointerSize)); // receiver 6787ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ tst(r2, Operand(kSmiTagMask)); 6797ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, &invoke); 6807ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ CompareObjectType(r2, r3, r3, JS_GLOBAL_OBJECT_TYPE); 6817ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, &global); 6827ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ cmp(r3, Operand(JS_BUILTINS_OBJECT_TYPE)); 6837ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(ne, &invoke); 6847ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6857ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Patch the receiver on the stack. 6867ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ bind(&global); 6877ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); 6887ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ str(r2, MemOperand(sp, argc * kPointerSize)); 6897ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ bind(&invoke); 6907ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman } 6917ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6927ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Invoke the function. 6937ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman ParameterCount actual(argc); 6947ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ InvokeFunction(r1, actual, JUMP_FUNCTION); 6957ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman} 6967ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6977ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 6987ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanvoid CallIC::GenerateMiss(MacroAssembler* masm, int argc) { 6997ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------- S t a t e ------------- 7007ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r2 : name 7017ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- lr : return address 7027ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------------------------------- 7037ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 7047ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateCallMiss(masm, argc, IC::kCallIC_Miss); 7057ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman} 7067ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 7077ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 7087ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanvoid CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 7097ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------- S t a t e ------------- 7107ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r2 : name 7117ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- lr : return address 7127ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------------------------------- 7137ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 714e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // Get the receiver of the function from the stack into r1. 715e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 7167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC); 7177ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateMiss(masm, argc); 718e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer} 719e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer 720e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer 7217ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanvoid CallIC::GenerateNormal(MacroAssembler* masm, int argc) { 72257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ----------- S t a t e ------------- 723e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // -- r2 : name 7247ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- lr : return address 7257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------------------------------- 726190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 727190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer GenerateCallNormal(masm, argc); 7287ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateMiss(masm, argc); 7297ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman} 7307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 7317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 7327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanvoid KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { 7337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------- S t a t e ------------- 7347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r2 : name 7357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- lr : return address 7367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------------------------------- 7377ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 738190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); 739190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer} 740190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 74157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 742190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramervoid KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 743190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // ----------- S t a t e ------------- 7447ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r2 : name 745190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- lr : return address 746190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // ----------------------------------- 747190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 748190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Get the receiver of the function from the stack into r1. 749190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 750190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 751190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Label do_call, slow_call, slow_load, slow_reload_receiver; 752190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Label check_number_dictionary, check_string, lookup_monomorphic_cache; 753190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Label index_smi, index_string; 754190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 755190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Check that the key is a smi. 756190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ JumpIfNotSmi(r2, &check_string); 757190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ bind(&index_smi); 758190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Now the key is known to be a smi. This place is also jumped to from below 7597ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // where a numeric string is converted to a smi. 7607ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 7617ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateKeyedLoadReceiverCheck( 7627ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman masm, r1, r0, r3, Map::kHasIndexedInterceptor, &slow_call); 76357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 76457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateFastArrayLoad( 76557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer masm, r1, r2, r4, r3, r0, r1, &check_number_dictionary, &slow_load); 76657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1, r0, r3); 76757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 76857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ bind(&do_call); 76957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // receiver in r1 is not used after this point. 77057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // r2: key 77157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // r1: function 77257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateFunctionTailCall(masm, argc, &slow_call, r0); 77357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 77457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ bind(&check_number_dictionary); 77557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // r2: key 77657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // r3: elements map 77757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // r4: elements 77857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Check whether the elements is a number dictionary. 77957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 78057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ cmp(r3, ip); 78157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ b(ne, &slow_load); 78257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ mov(r0, Operand(r2, ASR, kSmiTagSize)); 78357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // r0: untagged index 78457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateNumberDictionaryLoad(masm, &slow_load, r4, r2, r1, r0, r3, r5); 78557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1, r0, r3); 78657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ jmp(&do_call); 78757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 78857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ bind(&slow_load); 78957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // This branch is taken when calling KeyedCallIC_Miss is neither required 79057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // nor beneficial. 79157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1, r0, r3); 79257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ EnterInternalFrame(); 79357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ push(r2); // save the key 79457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ Push(r1, r2); // pass the receiver and the key 79557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ CallRuntime(Runtime::kKeyedGetProperty, 2); 79657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ pop(r2); // restore the key 79757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ LeaveInternalFrame(); 79857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ mov(r1, r0); 79957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ jmp(&do_call); 80057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 80157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ bind(&check_string); 80257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateKeyStringCheck(masm, r2, r0, r3, &index_string, &slow_call); 80357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 80457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // The key is known to be a symbol. 80557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // If the receiver is a regular JS object with slow properties then do 80657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // a quick inline probe of the receiver's dictionary. 80757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Otherwise do the monomorphic cache probe. 80857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateKeyedLoadReceiverCheck( 80957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer masm, r1, r0, r3, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); 81057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 81157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ ldr(r0, FieldMemOperand(r1, JSObject::kPropertiesOffset)); 81257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset)); 8137ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 81457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ cmp(r3, ip); 81557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ b(ne, &lookup_monomorphic_cache); 8167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 8177ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateDictionaryLoad(masm, &slow_load, r0, r2, r1, r3, r4); 81857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1, r0, r3); 81957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ jmp(&do_call); 82057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 82157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ bind(&lookup_monomorphic_cache); 82257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1, r0, r3); 82357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC); 82457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Fall through on miss. 8257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 826e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ bind(&slow_call); 827e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // This branch is taken if: 8287ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // - the receiver requires boxing or access check, 8297ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // - the key is neither smi nor symbol, 8307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // - the value loaded is not a function, 8317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // - there is hope that the runtime will create a monomorphic call stub 8327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // that will get fetched next time. 8337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ IncrementCounter(&Counters::keyed_call_generic_slow, 1, r0, r3); 8347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateMiss(masm, argc); 8357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 8367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ bind(&index_string); 8377ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ IndexFromHash(r3, r2); 8387ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Now jump to the place where smi keys are handled. 83957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ jmp(&index_smi); 84057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 84157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 84257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 84357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramervoid KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { 84457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ----------- S t a t e ------------- 84557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r2 : name 84657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- lr : return address 84757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ----------------------------------- 84857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 84957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Check if the name is a string. 85057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Label miss; 85157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ tst(r2, Operand(kSmiTagMask)); 85257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ b(eq, &miss); 85357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ IsObjectJSStringType(r2, r0, &miss); 85457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 85557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateCallNormal(masm, argc); 85657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ bind(&miss); 85757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateMiss(masm, argc); 85857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 85957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 86057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 86157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// Defined in ic.cc. 86257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin KramerObject* LoadIC_Miss(Arguments args); 86357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 86457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramervoid LoadIC::GenerateMegamorphic(MacroAssembler* masm) { 86557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ----------- S t a t e ------------- 86657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r2 : name 86757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- lr : return address 86857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r0 : receiver 86957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- sp[0] : receiver 87057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ----------------------------------- 87157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 87257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Probe the stub cache. 87357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, 87457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer NOT_IN_LOOP, 87557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer MONOMORPHIC); 87657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer StubCache::GenerateProbe(masm, flags, r0, r2, r3, r4, r5); 87757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 87857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Cache miss: Jump to runtime. 87957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateMiss(masm); 88057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 88157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 88257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 88357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramervoid LoadIC::GenerateNormal(MacroAssembler* masm) { 88457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ----------- S t a t e ------------- 88557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r2 : name 88657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- lr : return address 88757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r0 : receiver 88857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- sp[0] : receiver 88957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ----------------------------------- 89057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Label miss; 89157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 89257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateStringDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss); 89357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 89457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // r1: elements 89557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4); 89657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ Ret(); 89757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 89857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Cache miss: Jump to runtime. 89957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ bind(&miss); 90057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateMiss(masm); 90157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 90257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 90357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 90457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramervoid LoadIC::GenerateMiss(MacroAssembler* masm) { 90557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ----------- S t a t e ------------- 90657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r2 : name 90757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- lr : return address 90857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r0 : receiver 90957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- sp[0] : receiver 91057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ----------------------------------- 91157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 91257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ IncrementCounter(&Counters::load_miss, 1, r3, r4); 91357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 91457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ mov(r3, r0); 91557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ Push(r3, r2); 91657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 91757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Perform tail call to the entry. 91857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); 91957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ TailCallExternalReference(ref, 2, 1); 92057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 92157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 92257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// Returns the code marker, or the 0 if the code is not marked. 92357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramerstatic inline int InlinedICSiteMarker(Address address, 92457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address* inline_end_address) { 92557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (V8::UseCrankshaft()) return false; 92657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 92757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // If the instruction after the call site is not the pseudo instruction nop1 92857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // then this is not related to an inlined in-object property load. The nop1 92957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // instruction is located just after the call to the IC in the deferred code 93057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // handling the miss in the inlined code. After the nop1 instruction there is 93157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // a branch instruction for jumping back from the deferred code. 93257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address address_after_call = address + Assembler::kCallTargetAddressOffset; 93357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Instr instr_after_call = Assembler::instr_at(address_after_call); 93457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer int code_marker = MacroAssembler::GetCodeMarker(instr_after_call); 93557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 93657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // A negative result means the code is not marked. 93757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (code_marker <= 0) return 0; 93857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 93957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address address_after_nop = address_after_call + Assembler::kInstrSize; 94057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Instr instr_after_nop = Assembler::instr_at(address_after_nop); 94157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // There may be some reg-reg move and frame merging code to skip over before 94257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // the branch back from the DeferredReferenceGetKeyedValue code to the inlined 94357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // code. 94457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer while (!Assembler::IsBranch(instr_after_nop)) { 94557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer address_after_nop += Assembler::kInstrSize; 94657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer instr_after_nop = Assembler::instr_at(address_after_nop); 94757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } 94857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 94957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Find the end of the inlined code for handling the load. 95057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer int b_offset = 95157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::GetBranchOffset(instr_after_nop) + Assembler::kPcLoadDelta; 95257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ASSERT(b_offset < 0); // Jumping back from deferred code. 95357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer *inline_end_address = address_after_nop + b_offset; 95457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 95557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer return code_marker; 95657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 95757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 95857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 95957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramerbool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { 96057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (V8::UseCrankshaft()) return false; 96157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 96257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Find the end of the inlined code for handling the load if this is an 96357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // inlined IC call site. 96457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address inline_end_address; 96557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (InlinedICSiteMarker(address, &inline_end_address) 96657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer != Assembler::PROPERTY_ACCESS_INLINED) { 96757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer return false; 96857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } 96957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 97057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Patch the offset of the property load instruction (ldr r0, [r1, #+XXX]). 97157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // The immediate must be representable in 12 bits. 97257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ASSERT((JSObject::kMaxInstanceSize - JSObject::kHeaderSize) < (1 << 12)); 97357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address ldr_property_instr_address = 97457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer inline_end_address - Assembler::kInstrSize; 97557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ASSERT(Assembler::IsLdrRegisterImmediate( 97657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::instr_at(ldr_property_instr_address))); 97757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Instr ldr_property_instr = Assembler::instr_at(ldr_property_instr_address); 97857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ldr_property_instr = Assembler::SetLdrRegisterImmediateOffset( 97957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ldr_property_instr, offset - kHeapObjectTag); 98057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::instr_at_put(ldr_property_instr_address, ldr_property_instr); 98157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 98257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Indicate that code has changed. 98357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer CPU::FlushICache(ldr_property_instr_address, 1 * Assembler::kInstrSize); 98457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 98557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Patch the map check. 98657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // For PROPERTY_ACCESS_INLINED, the load map instruction is generated 98757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // 4 instructions before the end of the inlined code. 98857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // See codgen-arm.cc CodeGenerator::EmitNamedLoad. 98957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer int ldr_map_offset = -4; 99057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address ldr_map_instr_address = 99157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer inline_end_address + ldr_map_offset * Assembler::kInstrSize; 99257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::set_target_address_at(ldr_map_instr_address, 99357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer reinterpret_cast<Address>(map)); 99457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer return true; 99557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 99657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 99757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 99857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramerbool LoadIC::PatchInlinedContextualLoad(Address address, 99957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Object* map, 100057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Object* cell, 100157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer bool is_dont_delete) { 100257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Find the end of the inlined code for handling the contextual load if 100357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // this is inlined IC call site. 100457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address inline_end_address; 100557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer int marker = InlinedICSiteMarker(address, &inline_end_address); 100657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (!((marker == Assembler::PROPERTY_ACCESS_INLINED_CONTEXT) || 100757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer (marker == Assembler::PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE))) { 100857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer return false; 100957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } 101057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // On ARM we don't rely on the is_dont_delete argument as the hint is already 101157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // embedded in the code marker. 101257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer bool marker_is_dont_delete = 101357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer marker == Assembler::PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE; 101457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 101557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // These are the offsets from the end of the inlined code. 101657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // See codgen-arm.cc CodeGenerator::EmitNamedLoad. 101757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer int ldr_map_offset = marker_is_dont_delete ? -5: -8; 101857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer int ldr_cell_offset = marker_is_dont_delete ? -2: -5; 101957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (FLAG_debug_code && marker_is_dont_delete) { 102057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Three extra instructions were generated to check for the_hole_value. 102157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ldr_map_offset -= 3; 102257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ldr_cell_offset -= 3; 102357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } 102457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address ldr_map_instr_address = 102557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer inline_end_address + ldr_map_offset * Assembler::kInstrSize; 102657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address ldr_cell_instr_address = 102757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer inline_end_address + ldr_cell_offset * Assembler::kInstrSize; 102857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 102957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Patch the map check. 103057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::set_target_address_at(ldr_map_instr_address, 103157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer reinterpret_cast<Address>(map)); 103257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Patch the cell address. 103357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::set_target_address_at(ldr_cell_instr_address, 103457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer reinterpret_cast<Address>(cell)); 103557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 103657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer return true; 103757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 103857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 103957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 104057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramerbool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { 104157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (V8::UseCrankshaft()) return false; 104257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 104357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Find the end of the inlined code for the store if there is an 104457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // inlined version of the store. 104557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address inline_end_address; 104657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (InlinedICSiteMarker(address, &inline_end_address) 104757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer != Assembler::PROPERTY_ACCESS_INLINED) { 104857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer return false; 104957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } 105057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 105157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Compute the address of the map load instruction. 105257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address ldr_map_instr_address = 105357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer inline_end_address - 105457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer (CodeGenerator::GetInlinedNamedStoreInstructionsAfterPatch() * 105557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::kInstrSize); 105657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 105757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Update the offsets if initializing the inlined store. No reason 105857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // to update the offsets when clearing the inlined version because 105957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // it will bail out in the map check. 106057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (map != Heap::null_value()) { 106157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Patch the offset in the actual store instruction. 106257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address str_property_instr_address = 106357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ldr_map_instr_address + 3 * Assembler::kInstrSize; 106457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Instr str_property_instr = Assembler::instr_at(str_property_instr_address); 106557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ASSERT(Assembler::IsStrRegisterImmediate(str_property_instr)); 106657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer str_property_instr = Assembler::SetStrRegisterImmediateOffset( 106757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer str_property_instr, offset - kHeapObjectTag); 106857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::instr_at_put(str_property_instr_address, str_property_instr); 106957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 107057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Patch the offset in the add instruction that is part of the 107157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // write barrier. 107257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address add_offset_instr_address = 107357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer str_property_instr_address + Assembler::kInstrSize; 107457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Instr add_offset_instr = Assembler::instr_at(add_offset_instr_address); 107557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ASSERT(Assembler::IsAddRegisterImmediate(add_offset_instr)); 107657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer add_offset_instr = Assembler::SetAddRegisterImmediateOffset( 107757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer add_offset_instr, offset - kHeapObjectTag); 107857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::instr_at_put(add_offset_instr_address, add_offset_instr); 107957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 108057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Indicate that code has changed. 108157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer CPU::FlushICache(str_property_instr_address, 2 * Assembler::kInstrSize); 108257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } 108357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 108457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Patch the map check. 108557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::set_target_address_at(ldr_map_instr_address, 108657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer reinterpret_cast<Address>(map)); 108757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 108857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer return true; 108957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 109057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 109157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 109257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramerbool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { 109357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (V8::UseCrankshaft()) return false; 109457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 109557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address inline_end_address; 109657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (InlinedICSiteMarker(address, &inline_end_address) 109757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer != Assembler::PROPERTY_ACCESS_INLINED) { 109857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer return false; 109957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } 110057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 110157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Patch the map check. 110257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address ldr_map_instr_address = 110357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer inline_end_address - 110457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer (CodeGenerator::GetInlinedKeyedLoadInstructionsAfterPatch() * 110557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::kInstrSize); 110657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::set_target_address_at(ldr_map_instr_address, 110757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer reinterpret_cast<Address>(map)); 110857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer return true; 110957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 111057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 111157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 111257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramerbool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { 111357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (V8::UseCrankshaft()) return false; 111457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 111557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Find the end of the inlined code for handling the store if this is an 111657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // inlined IC call site. 111757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address inline_end_address; 111857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer if (InlinedICSiteMarker(address, &inline_end_address) 111957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer != Assembler::PROPERTY_ACCESS_INLINED) { 112057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer return false; 112157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer } 112257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 112357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Patch the map check. 112457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Address ldr_map_instr_address = 112557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer inline_end_address - 112657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer (CodeGenerator::kInlinedKeyedStoreInstructionsAfterPatch * 112757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::kInstrSize); 112857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer Assembler::set_target_address_at(ldr_map_instr_address, 112957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer reinterpret_cast<Address>(map)); 113057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer return true; 113157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 113257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 113357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 113457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin KramerObject* KeyedLoadIC_Miss(Arguments args); 113557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 113657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 113757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramervoid KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 113857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ---------- S t a t e -------------- 113957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- lr : return address 114057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r0 : key 114157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r1 : receiver 114257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ----------------------------------- 114357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 114457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ IncrementCounter(&Counters::keyed_load_miss, 1, r3, r4); 114557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 114657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ Push(r1, r0); 114757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 114857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); 114957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ TailCallExternalReference(ref, 2, 1); 115057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 115157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 115257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 115357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramervoid KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 115457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ---------- S t a t e -------------- 115557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- lr : return address 115657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r0 : key 115757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r1 : receiver 115857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ----------------------------------- 115957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 116057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ Push(r1, r0); 116157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 116257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 116357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer} 116457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 116557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 116657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramervoid KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 116757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // ---------- S t a t e -------------- 116857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- lr : return address 116957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r0 : key 117057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // -- r1 : receiver 11717ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------------------------------- 11727ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Label slow, check_string, index_smi, index_string, property_array_property; 11737ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Label check_pixel_array, probe_dictionary, check_number_dictionary; 11747ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 11757ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register key = r0; 11767ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register receiver = r1; 11777ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 11787ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check that the key is a smi. 11797ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ JumpIfNotSmi(key, &check_string); 11807ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ bind(&index_smi); 11817ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Now the key is known to be a smi. This place is also jumped to from below 118257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // where a numeric string is converted to a smi. 118357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 118457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateKeyedLoadReceiverCheck( 118557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow); 118657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 11877ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check the "has fast elements" bit in the receiver's map which is 11887ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // now in r2. 11897ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldrb(r3, FieldMemOperand(r2, Map::kBitField2Offset)); 11907ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ tst(r3, Operand(1 << Map::kHasFastElements)); 11917ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, &check_pixel_array); 11927ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 11937ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateFastArrayLoad( 11947ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman masm, receiver, key, r4, r3, r2, r0, NULL, &slow); 11957ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ IncrementCounter(&Counters::keyed_load_generic_smi, 1, r2, r3); 11967ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ Ret(); 11977ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 11987ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check whether the elements is a pixel array. 11997ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // r0: key 12007ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // r1: receiver 12017ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ bind(&check_pixel_array); 12027ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 12037ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateFastPixelArrayLoad(masm, 12047ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman r1, 12057ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman r0, 12067ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman r3, 12077ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman r4, 12087ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman r2, 12097ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman r5, 12107ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman r0, 121157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer &check_number_dictionary, 121257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer NULL, 121357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer &slow); 121457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 121557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ bind(&check_number_dictionary); 12167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check whether the elements is a number dictionary. 12177ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // r0: key 121857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // r3: elements map 121957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // r4: elements 122057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 122157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ cmp(r3, ip); 122257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ b(ne, &slow); 122357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ mov(r2, Operand(r0, ASR, kSmiTagSize)); 122457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateNumberDictionaryLoad(masm, &slow, r4, r0, r0, r2, r3, r5); 122557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ Ret(); 122657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 122757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Slow case, key and receiver still in r0 and r1. 122857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ bind(&slow); 122957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r2, r3); 12307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateRuntimeGetProperty(masm); 12317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 12327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ bind(&check_string); 12337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateKeyStringCheck(masm, key, r2, r3, &index_string, &slow); 12347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 123557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateKeyedLoadReceiverCheck( 12367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman masm, receiver, r2, r3, Map::kHasNamedInterceptor, &slow); 123757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer 12387ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // If the receiver is a fast-case object, check the keyed lookup 12397ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // cache. Otherwise probe the dictionary. 12407ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset)); 12417ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); 12427ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 12437ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ cmp(r4, ip); 12447ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, &probe_dictionary); 12457ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 12467ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Load the map of the receiver, compute the keyed lookup cache hash 12477ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // based on 32 bits of the map pointer and the string hash. 12487ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 12497ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift)); 12507ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(r4, FieldMemOperand(r0, String::kHashFieldOffset)); 12517ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ eor(r3, r3, Operand(r4, ASR, String::kHashShift)); 12527ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ And(r3, r3, Operand(KeyedLookupCache::kCapacityMask)); 12537ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 12547ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Load the key (consisting of map and symbol) from the cache and 1255e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer // check for match. 1256e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer ExternalReference cache_keys = ExternalReference::keyed_lookup_cache_keys(); 125757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ mov(r4, Operand(cache_keys)); 1258190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1)); 1259190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); // Move r4 to symbol. 1260e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ cmp(r2, r5); 1261e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ b(ne, &slow); 126257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ ldr(r5, MemOperand(r4)); 1263190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ cmp(r0, r5); 1264e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ b(ne, &slow); 1265e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer 1266190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Get field offset. 1267190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // r0 : key 1268190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // r1 : receiver 1269190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // r2 : receiver's map 1270190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // r3 : lookup cache index 1271190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer ExternalReference cache_field_offsets 1272190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer = ExternalReference::keyed_lookup_cache_field_offsets(); 1273190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ mov(r4, Operand(cache_field_offsets)); 1274190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2)); 1275190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset)); 1276e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ sub(r5, r5, r6, SetCC); 1277190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ b(ge, &property_array_property); 1278190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1279190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Load in-object property. 1280190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldrb(r6, FieldMemOperand(r2, Map::kInstanceSizeOffset)); 1281190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ add(r6, r6, r5); // Index from start of object. 1282190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ sub(r1, r1, Operand(kHeapObjectTag)); // Remove the heap tag. 1283190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldr(r0, MemOperand(r1, r6, LSL, kPointerSizeLog2)); 1284190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1, r2, r3); 1285190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ Ret(); 1286190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1287190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Load property array property. 1288190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ bind(&property_array_property); 12897ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(r1, FieldMemOperand(r1, JSObject::kPropertiesOffset)); 1290190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ add(r1, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 1291190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldr(r0, MemOperand(r1, r5, LSL, kPointerSizeLog2)); 1292190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1, r2, r3); 1293190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ Ret(); 1294190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1295190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Do a quick inline probe of the receiver's dictionary, if it 1296190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // exists. 1297190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ bind(&probe_dictionary); 1298190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // r1: receiver 1299190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // r0: key 1300190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // r3: elements 1301190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 1302190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 1303190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer GenerateGlobalInstanceTypeCheck(masm, r2, &slow); 1304190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Load the property to r0. 1305190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4); 1306190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1, r2, r3); 1307190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ Ret(); 1308190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1309190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ bind(&index_string); 1310190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ IndexFromHash(r3, key); 1311190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Now jump to the place where smi keys are handled. 1312190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ jmp(&index_smi); 1313190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer} 1314190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1315190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1316190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramervoid KeyedLoadIC::GenerateString(MacroAssembler* masm) { 1317190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // ---------- S t a t e -------------- 1318190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- lr : return address 1319190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- r0 : key (index) 1320190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- r1 : receiver 1321190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // ----------------------------------- 1322190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Label miss; 1323190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1324190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Register receiver = r1; 13257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register index = r0; 13267ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register scratch1 = r2; 1327190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Register scratch2 = r3; 1328190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Register result = r0; 1329190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1330190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer StringCharAtGenerator char_at_generator(receiver, 1331190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer index, 1332190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer scratch1, 1333190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer scratch2, 1334190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer result, 1335190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer &miss, // When not a string. 1336190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer &miss, // When not a number. 1337190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer &miss, // When index out of range. 1338190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer STRING_INDEX_IS_ARRAY_INDEX); 1339190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer char_at_generator.GenerateFast(masm); 1340190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ Ret(); 1341190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1342190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer StubRuntimeCallHelper call_helper; 1343190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer char_at_generator.GenerateSlow(masm, call_helper); 1344190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1345190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ bind(&miss); 1346190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer GenerateMiss(masm); 1347190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer} 1348190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1349190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1350190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramervoid KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 1351190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // ---------- S t a t e -------------- 1352190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- lr : return address 1353190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- r0 : key 1354190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- r1 : receiver 1355190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // ----------------------------------- 1356190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer Label slow; 1357190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1358190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Check that the receiver isn't a smi. 1359190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ JumpIfSmi(r1, &slow); 1360190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1361190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Check that the key is an array index, that is Uint32. 1362190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ tst(r0, Operand(kSmiTagMask | kSmiSignMask)); 1363190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ b(ne, &slow); 1364190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1365190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Get the map of the receiver. 1366190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 1367190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1368190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Check that it has indexed interceptor and access checks 1369190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // are not enabled for this object. 137057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset)); 1371190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ and_(r3, r3, Operand(kSlowCaseBitFieldMask)); 1372190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ cmp(r3, Operand(1 << Map::kHasIndexedInterceptor)); 1373190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ b(ne, &slow); 1374190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1375190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Everything is fine, call runtime. 1376190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ Push(r1, r0); // Receiver, key. 1377190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1378190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // Perform tail call to the entry. 1379190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ TailCallExternalReference(ExternalReference( 1380190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); 1381190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1382190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer __ bind(&slow); 1383190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer GenerateMiss(masm); 1384190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer} 1385190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1386190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 1387190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramervoid KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { 1388190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // ---------- S t a t e -------------- 1389190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- r0 : value 1390190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- r1 : key 1391190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- r2 : receiver 1392190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // -- lr : return address 1393190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer // ----------------------------------- 1394190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer 13957ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Push receiver, key and value for runtime call. 13967ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ Push(r2, r1, r0); 13977ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 13987ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); 13997ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ TailCallExternalReference(ref, 3, 1); 14007ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman} 14017ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 14027ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 14037ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanvoid KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, 14047ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman StrictModeFlag strict_mode) { 14057ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ---------- S t a t e -------------- 14067ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r0 : value 14077ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r1 : key 14087ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r2 : receiver 14097ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- lr : return address 14107ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------------------------------- 14117ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 14127ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Push receiver, key and value for runtime call. 14137ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ Push(r2, r1, r0); 14147ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 14157ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ mov(r1, Operand(Smi::FromInt(NONE))); // PropertyAttributes 14167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ mov(r0, Operand(Smi::FromInt(strict_mode))); // Strict mode. 14177ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ Push(r1, r0); 14187ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 14197ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ TailCallRuntime(Runtime::kSetProperty, 5, 1); 14207ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman} 14217ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 14227ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 14237ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanvoid KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, 14247ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman StrictModeFlag strict_mode) { 14257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ---------- S t a t e -------------- 14267ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r0 : value 14277ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r1 : key 14287ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- r2 : receiver 14297ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // -- lr : return address 14307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // ----------------------------------- 14317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Label slow, fast, array, extra, check_pixel_array; 14327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 14337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Register usage. 14347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register value = r0; 14357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register key = r1; 14367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register receiver = r2; 14377ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman Register elements = r3; // Elements array of the receiver. 14387ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // r4 and r5 are used as general scratch registers. 14397ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 14407ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check that the key is a smi. 14417ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ tst(key, Operand(kSmiTagMask)); 14427ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(ne, &slow); 14437ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check that the object isn't a smi. 14447ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ tst(receiver, Operand(kSmiTagMask)); 14457ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, &slow); 14467ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Get the map of the object. 1447e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer __ ldr(r4, FieldMemOperand(receiver, HeapObject::kMapOffset)); 14487ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check that the receiver does not require access checks. We need 14497ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // to do this because this generic stub does not perform map checks. 14507ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldrb(ip, FieldMemOperand(r4, Map::kBitFieldOffset)); 14517ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded)); 14527ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(ne, &slow); 14537ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check if the object is a JS array or not. 14547ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 14557ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ cmp(r4, Operand(JS_ARRAY_TYPE)); 14567ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(eq, &array); 14577ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check that the object is some kind of JS object. 14587ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ cmp(r4, Operand(FIRST_JS_OBJECT_TYPE)); 14597ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(lt, &slow); 14607ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 14617ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Object case: Check key against length in the elements array. 14627ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 14637ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check that the object is in fast mode and writable. 14647ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset)); 14657ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 14667ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ cmp(r4, ip); 14677ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ b(ne, &check_pixel_array); 14687ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Check array bounds. Both the key and the length of FixedArray are smis. 146957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); 14707ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ cmp(key, Operand(ip)); 147157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer __ b(lo, &fast); 14727ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 147357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Slow case, handle jump to runtime. 14747ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ bind(&slow); 14757ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Entry registers are intact. 14767ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // r0: value. 147757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // r1: key. 14787ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // r2: receiver. 147957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer GenerateRuntimeSetProperty(masm, strict_mode); 14807ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 148157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer // Check whether the elements is a pixel array. 14827ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // r4: elements map. 14837ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman __ bind(&check_pixel_array); 14847ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman GenerateFastPixelArrayStore(masm, 14857ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman r2, 14867ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman r1, 14877ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman r0, 14887ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman elements, 14897ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman r4, 14907ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman r5, 14917ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman r6, 14927ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman false, 14937ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman false, 149457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer NULL, 14957ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman &slow, 14967ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman &slow, 14977ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman &slow); 14987ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman 14997ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // Extra capacity case: Check if there is extra capacity to 15007ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman // perform the store and update the length. Used for adding one 1501 // element to the array by writing to array[array.length]. 1502 __ bind(&extra); 1503 // Condition code from comparing key and array length is still available. 1504 __ b(ne, &slow); // Only support writing to writing to array[array.length]. 1505 // Check for room in the elements backing store. 1506 // Both the key and the length of FixedArray are smis. 1507 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); 1508 __ cmp(key, Operand(ip)); 1509 __ b(hs, &slow); 1510 // Calculate key + 1 as smi. 1511 ASSERT_EQ(0, kSmiTag); 1512 __ add(r4, key, Operand(Smi::FromInt(1))); 1513 __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); 1514 __ b(&fast); 1515 1516 // Array case: Get the length and the elements array from the JS 1517 // array. Check that the array is in fast mode (and writable); if it 1518 // is the length is always a smi. 1519 __ bind(&array); 1520 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 1521 __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset)); 1522 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 1523 __ cmp(r4, ip); 1524 __ b(ne, &slow); 1525 1526 // Check the key against the length in the array. 1527 __ ldr(ip, FieldMemOperand(receiver, JSArray::kLengthOffset)); 1528 __ cmp(key, Operand(ip)); 1529 __ b(hs, &extra); 1530 // Fall through to fast case. 1531 1532 __ bind(&fast); 1533 // Fast case, store the value to the elements backing store. 1534 __ add(r5, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 1535 __ add(r5, r5, Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); 1536 __ str(value, MemOperand(r5)); 1537 // Skip write barrier if the written value is a smi. 1538 __ tst(value, Operand(kSmiTagMask)); 1539 __ Ret(eq); 1540 // Update write barrier for the elements array address. 1541 __ sub(r4, r5, Operand(elements)); 1542 __ RecordWrite(elements, Operand(r4), r5, r6); 1543 1544 __ Ret(); 1545} 1546 1547 1548void StoreIC::GenerateMegamorphic(MacroAssembler* masm, 1549 StrictModeFlag strict_mode) { 1550 // ----------- S t a t e ------------- 1551 // -- r0 : value 1552 // -- r1 : receiver 1553 // -- r2 : name 1554 // -- lr : return address 1555 // ----------------------------------- 1556 1557 // Get the receiver from the stack and probe the stub cache. 1558 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, 1559 NOT_IN_LOOP, 1560 MONOMORPHIC, 1561 strict_mode); 1562 StubCache::GenerateProbe(masm, flags, r1, r2, r3, r4, r5); 1563 1564 // Cache miss: Jump to runtime. 1565 GenerateMiss(masm); 1566} 1567 1568 1569void StoreIC::GenerateMiss(MacroAssembler* masm) { 1570 // ----------- S t a t e ------------- 1571 // -- r0 : value 1572 // -- r1 : receiver 1573 // -- r2 : name 1574 // -- lr : return address 1575 // ----------------------------------- 1576 1577 __ Push(r1, r2, r0); 1578 1579 // Perform tail call to the entry. 1580 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss)); 1581 __ TailCallExternalReference(ref, 3, 1); 1582} 1583 1584 1585void StoreIC::GenerateArrayLength(MacroAssembler* masm) { 1586 // ----------- S t a t e ------------- 1587 // -- r0 : value 1588 // -- r1 : receiver 1589 // -- r2 : name 1590 // -- lr : return address 1591 // ----------------------------------- 1592 // 1593 // This accepts as a receiver anything JSObject::SetElementsLength accepts 1594 // (currently anything except for external and pixel arrays which means 1595 // anything with elements of FixedArray type.), but currently is restricted 1596 // to JSArray. 1597 // Value must be a number, but only smis are accepted as the most common case. 1598 1599 Label miss; 1600 1601 Register receiver = r1; 1602 Register value = r0; 1603 Register scratch = r3; 1604 1605 // Check that the receiver isn't a smi. 1606 __ JumpIfSmi(receiver, &miss); 1607 1608 // Check that the object is a JS array. 1609 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); 1610 __ b(ne, &miss); 1611 1612 // Check that elements are FixedArray. 1613 // We rely on StoreIC_ArrayLength below to deal with all types of 1614 // fast elements (including COW). 1615 __ ldr(scratch, FieldMemOperand(receiver, JSArray::kElementsOffset)); 1616 __ CompareObjectType(scratch, scratch, scratch, FIXED_ARRAY_TYPE); 1617 __ b(ne, &miss); 1618 1619 // Check that value is a smi. 1620 __ JumpIfNotSmi(value, &miss); 1621 1622 // Prepare tail call to StoreIC_ArrayLength. 1623 __ Push(receiver, value); 1624 1625 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength)); 1626 __ TailCallExternalReference(ref, 2, 1); 1627 1628 __ bind(&miss); 1629 1630 GenerateMiss(masm); 1631} 1632 1633 1634void StoreIC::GenerateNormal(MacroAssembler* masm) { 1635 // ----------- S t a t e ------------- 1636 // -- r0 : value 1637 // -- r1 : receiver 1638 // -- r2 : name 1639 // -- lr : return address 1640 // ----------------------------------- 1641 Label miss; 1642 1643 GenerateStringDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss); 1644 1645 GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5); 1646 __ IncrementCounter(&Counters::store_normal_hit, 1, r4, r5); 1647 __ Ret(); 1648 1649 __ bind(&miss); 1650 __ IncrementCounter(&Counters::store_normal_miss, 1, r4, r5); 1651 GenerateMiss(masm); 1652} 1653 1654 1655void StoreIC::GenerateGlobalProxy(MacroAssembler* masm, 1656 StrictModeFlag strict_mode) { 1657 // ----------- S t a t e ------------- 1658 // -- r0 : value 1659 // -- r1 : receiver 1660 // -- r2 : name 1661 // -- lr : return address 1662 // ----------------------------------- 1663 1664 __ Push(r1, r2, r0); 1665 1666 __ mov(r1, Operand(Smi::FromInt(NONE))); // PropertyAttributes 1667 __ mov(r0, Operand(Smi::FromInt(strict_mode))); 1668 __ Push(r1, r0); 1669 1670 // Do tail-call to runtime routine. 1671 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); 1672} 1673 1674 1675#undef __ 1676 1677 1678Condition CompareIC::ComputeCondition(Token::Value op) { 1679 switch (op) { 1680 case Token::EQ_STRICT: 1681 case Token::EQ: 1682 return eq; 1683 case Token::LT: 1684 return lt; 1685 case Token::GT: 1686 // Reverse left and right operands to obtain ECMA-262 conversion order. 1687 return lt; 1688 case Token::LTE: 1689 // Reverse left and right operands to obtain ECMA-262 conversion order. 1690 return ge; 1691 case Token::GTE: 1692 return ge; 1693 default: 1694 UNREACHABLE(); 1695 return kNoCondition; 1696 } 1697} 1698 1699 1700void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { 1701 HandleScope scope; 1702 Handle<Code> rewritten; 1703 State previous_state = GetState(); 1704 State state = TargetState(previous_state, false, x, y); 1705 if (state == GENERIC) { 1706 CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS, r1, r0); 1707 rewritten = stub.GetCode(); 1708 } else { 1709 ICCompareStub stub(op_, state); 1710 rewritten = stub.GetCode(); 1711 } 1712 set_target(*rewritten); 1713 1714#ifdef DEBUG 1715 if (FLAG_trace_ic) { 1716 PrintF("[CompareIC (%s->%s)#%s]\n", 1717 GetStateName(previous_state), 1718 GetStateName(state), 1719 Token::Name(op_)); 1720 } 1721#endif 1722 1723 // Activate inlined smi code. 1724 if (previous_state == UNINITIALIZED) { 1725 PatchInlinedSmiCode(address()); 1726 } 1727} 1728 1729 1730void PatchInlinedSmiCode(Address address) { 1731 Address cmp_instruction_address = 1732 address + Assembler::kCallTargetAddressOffset; 1733 1734 // If the instruction following the call is not a cmp rx, #yyy, nothing 1735 // was inlined. 1736 Instr instr = Assembler::instr_at(cmp_instruction_address); 1737 if (!Assembler::IsCmpImmediate(instr)) { 1738 return; 1739 } 1740 1741 // The delta to the start of the map check instruction and the 1742 // condition code uses at the patched jump. 1743 int delta = Assembler::GetCmpImmediateRawImmediate(instr); 1744 delta += 1745 Assembler::GetCmpImmediateRegister(instr).code() * kOff12Mask; 1746 // If the delta is 0 the instruction is cmp r0, #0 which also signals that 1747 // nothing was inlined. 1748 if (delta == 0) { 1749 return; 1750 } 1751 1752#ifdef DEBUG 1753 if (FLAG_trace_ic) { 1754 PrintF("[ patching ic at %p, cmp=%p, delta=%d\n", 1755 address, cmp_instruction_address, delta); 1756 } 1757#endif 1758 1759 Address patch_address = 1760 cmp_instruction_address - delta * Instruction::kInstrSize; 1761 Instr instr_at_patch = Assembler::instr_at(patch_address); 1762 Instr branch_instr = 1763 Assembler::instr_at(patch_address + Instruction::kInstrSize); 1764 ASSERT(Assembler::IsCmpRegister(instr_at_patch)); 1765 ASSERT_EQ(Assembler::GetRn(instr_at_patch).code(), 1766 Assembler::GetRm(instr_at_patch).code()); 1767 ASSERT(Assembler::IsBranch(branch_instr)); 1768 if (Assembler::GetCondition(branch_instr) == eq) { 1769 // This is patching a "jump if not smi" site to be active. 1770 // Changing 1771 // cmp rx, rx 1772 // b eq, <target> 1773 // to 1774 // tst rx, #kSmiTagMask 1775 // b ne, <target> 1776 CodePatcher patcher(patch_address, 2); 1777 Register reg = Assembler::GetRn(instr_at_patch); 1778 patcher.masm()->tst(reg, Operand(kSmiTagMask)); 1779 patcher.EmitCondition(ne); 1780 } else { 1781 ASSERT(Assembler::GetCondition(branch_instr) == ne); 1782 // This is patching a "jump if smi" site to be active. 1783 // Changing 1784 // cmp rx, rx 1785 // b ne, <target> 1786 // to 1787 // tst rx, #kSmiTagMask 1788 // b eq, <target> 1789 CodePatcher patcher(patch_address, 2); 1790 Register reg = Assembler::GetRn(instr_at_patch); 1791 patcher.masm()->tst(reg, Operand(kSmiTagMask)); 1792 patcher.EmitCondition(eq); 1793 } 1794} 1795 1796 1797} } // namespace v8::internal 1798 1799#endif // V8_TARGET_ARCH_ARM 1800