blob: c92296da3e9c74ec177050792c2be6b89a6e7aed [file] [log] [blame]
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +000030#if defined(V8_TARGET_ARCH_ARM)
31
fschneider@chromium.org013f3e12010-04-26 13:27:52 +000032#include "assembler-arm.h"
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000033#include "code-stubs.h"
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000034#include "codegen.h"
fschneider@chromium.org013f3e12010-04-26 13:27:52 +000035#include "disasm.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036#include "ic-inl.h"
37#include "runtime.h"
38#include "stub-cache.h"
39
kasperl@chromium.org71affb52009-05-26 05:44:31 +000040namespace v8 {
41namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000042
43
44// ----------------------------------------------------------------------------
45// Static IC stub generators.
46//
47
ager@chromium.org65dad4b2009-04-23 08:48:43 +000048#define __ ACCESS_MASM(masm)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000049
fschneider@chromium.org40b9da32010-06-28 11:29:21 +000050
51static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm,
52 Register type,
53 Label* global_object) {
54 // Register usage:
55 // type: holds the receiver instance type on entry.
56 __ cmp(type, Operand(JS_GLOBAL_OBJECT_TYPE));
57 __ b(eq, global_object);
58 __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE));
59 __ b(eq, global_object);
60 __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE));
61 __ b(eq, global_object);
62}
63
64
65// Generated code falls through if the receiver is a regular non-global
66// JS object with slow properties and no interceptors.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +000067static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
68 Register receiver,
69 Register elements,
70 Register t0,
71 Register t1,
72 Label* miss) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +000073 // Register usage:
74 // receiver: holds the receiver on entry and is unchanged.
75 // elements: holds the property dictionary on fall through.
76 // Scratch registers:
77 // t0: used to holds the receiver map.
78 // t1: used to holds the receiver instance type, receiver bit mask and
79 // elements map.
80
81 // Check that the receiver isn't a smi.
82 __ tst(receiver, Operand(kSmiTagMask));
83 __ b(eq, miss);
84
85 // Check that the receiver is a valid JS object.
ricow@chromium.orgd2be9012011-06-01 06:00:58 +000086 __ CompareObjectType(receiver, t0, t1, FIRST_SPEC_OBJECT_TYPE);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +000087 __ b(lt, miss);
88
89 // If this assert fails, we have to check upper bound too.
ricow@chromium.orgd2be9012011-06-01 06:00:58 +000090 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +000091
92 GenerateGlobalInstanceTypeCheck(masm, t1, miss);
93
94 // Check that the global object does not require access checks.
95 __ ldrb(t1, FieldMemOperand(t0, Map::kBitFieldOffset));
96 __ tst(t1, Operand((1 << Map::kIsAccessCheckNeeded) |
97 (1 << Map::kHasNamedInterceptor)));
ager@chromium.org378b34e2011-01-28 08:04:38 +000098 __ b(ne, miss);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +000099
100 __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
101 __ ldr(t1, FieldMemOperand(elements, HeapObject::kMapOffset));
102 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
103 __ cmp(t1, ip);
ager@chromium.org378b34e2011-01-28 08:04:38 +0000104 __ b(ne, miss);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000105}
106
107
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000108// Helper function used from LoadIC/CallIC GenerateNormal.
109//
110// elements: Property dictionary. It is not clobbered if a jump to the miss
111// label is done.
112// name: Property name. It is not clobbered if a jump to the miss label is
113// done
114// result: Register for the result. It is only updated if a jump to the miss
115// label is not done. Can be the same as elements or name clobbering
116// one of these in the case of not jumping to the miss label.
117// The two scratch registers need to be different from elements, name and
118// result.
119// The generated code assumes that the receiver has slow properties,
120// is not a global object and does not have interceptors.
121static void GenerateDictionaryLoad(MacroAssembler* masm,
122 Label* miss,
123 Register elements,
124 Register name,
125 Register result,
126 Register scratch1,
127 Register scratch2) {
128 // Main use of the scratch registers.
129 // scratch1: Used as temporary and to hold the capacity of the property
130 // dictionary.
131 // scratch2: Used as temporary.
132 Label done;
133
134 // Probe the dictionary.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000135 StringDictionaryLookupStub::GeneratePositiveLookup(masm,
136 miss,
137 &done,
138 elements,
139 name,
140 scratch1,
141 scratch2);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000142
143 // If probing finds an entry check that the value is a normal
144 // property.
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000145 __ bind(&done); // scratch2 == elements + 4 * index
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000146 const int kElementsStartOffset = StringDictionary::kHeaderSize +
147 StringDictionary::kElementsStartIndex * kPointerSize;
148 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
149 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000150 __ tst(scratch1, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize));
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000151 __ b(ne, miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000152
153 // Get the value at the masked, scaled index and return.
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000154 __ ldr(result,
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000155 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000156}
157
158
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000159// Helper function used from StoreIC::GenerateNormal.
160//
161// elements: Property dictionary. It is not clobbered if a jump to the miss
162// label is done.
163// name: Property name. It is not clobbered if a jump to the miss label is
164// done
165// value: The value to store.
166// The two scratch registers need to be different from elements, name and
167// result.
168// The generated code assumes that the receiver has slow properties,
169// is not a global object and does not have interceptors.
170static void GenerateDictionaryStore(MacroAssembler* masm,
171 Label* miss,
172 Register elements,
173 Register name,
174 Register value,
175 Register scratch1,
176 Register scratch2) {
177 // Main use of the scratch registers.
178 // scratch1: Used as temporary and to hold the capacity of the property
179 // dictionary.
180 // scratch2: Used as temporary.
181 Label done;
182
183 // Probe the dictionary.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000184 StringDictionaryLookupStub::GeneratePositiveLookup(masm,
185 miss,
186 &done,
187 elements,
188 name,
189 scratch1,
190 scratch2);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000191
192 // If probing finds an entry in the dictionary check that the value
193 // is a normal property that is not read only.
194 __ bind(&done); // scratch2 == elements + 4 * index
195 const int kElementsStartOffset = StringDictionary::kHeaderSize +
196 StringDictionary::kElementsStartIndex * kPointerSize;
197 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
198 const int kTypeAndReadOnlyMask
199 = (PropertyDetails::TypeField::mask() |
200 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
201 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
202 __ tst(scratch1, Operand(kTypeAndReadOnlyMask));
203 __ b(ne, miss);
204
205 // Store the value at the masked, scaled index and return.
206 const int kValueOffset = kElementsStartOffset + kPointerSize;
207 __ add(scratch2, scratch2, Operand(kValueOffset - kHeapObjectTag));
208 __ str(value, MemOperand(scratch2));
209
210 // Update the write barrier. Make sure not to clobber the value.
211 __ mov(scratch1, value);
212 __ RecordWrite(elements, scratch2, scratch1);
213}
214
215
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000216static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
217 Label* miss,
218 Register elements,
219 Register key,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000220 Register result,
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000221 Register t0,
222 Register t1,
223 Register t2) {
224 // Register use:
225 //
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000226 // elements - holds the slow-case elements of the receiver on entry.
227 // Unchanged unless 'result' is the same register.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000228 //
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000229 // key - holds the smi key on entry.
230 // Unchanged unless 'result' is the same register.
231 //
232 // result - holds the result on exit if the load succeeded.
233 // Allowed to be the same as 'key' or 'result'.
234 // Unchanged on bailout so 'key' or 'result' can be used
235 // in further computation.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000236 //
237 // Scratch registers:
238 //
239 // t0 - holds the untagged key on entry and holds the hash once computed.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000240 //
241 // t1 - used to hold the capacity mask of the dictionary
242 //
243 // t2 - used for the index into the dictionary.
244 Label done;
245
246 // Compute the hash code from the untagged key. This must be kept in sync
247 // with ComputeIntegerHash in utils.h.
248 //
249 // hash = ~hash + (hash << 15);
250 __ mvn(t1, Operand(t0));
251 __ add(t0, t1, Operand(t0, LSL, 15));
252 // hash = hash ^ (hash >> 12);
253 __ eor(t0, t0, Operand(t0, LSR, 12));
254 // hash = hash + (hash << 2);
255 __ add(t0, t0, Operand(t0, LSL, 2));
256 // hash = hash ^ (hash >> 4);
257 __ eor(t0, t0, Operand(t0, LSR, 4));
258 // hash = hash * 2057;
259 __ mov(t1, Operand(2057));
260 __ mul(t0, t0, t1);
261 // hash = hash ^ (hash >> 16);
262 __ eor(t0, t0, Operand(t0, LSR, 16));
263
264 // Compute the capacity mask.
265 __ ldr(t1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset));
266 __ mov(t1, Operand(t1, ASR, kSmiTagSize)); // convert smi to int
267 __ sub(t1, t1, Operand(1));
268
269 // Generate an unrolled loop that performs a few probes before giving up.
270 static const int kProbes = 4;
271 for (int i = 0; i < kProbes; i++) {
272 // Use t2 for index calculations and keep the hash intact in t0.
273 __ mov(t2, t0);
274 // Compute the masked index: (hash + i + i * i) & mask.
275 if (i > 0) {
276 __ add(t2, t2, Operand(NumberDictionary::GetProbeOffset(i)));
277 }
278 __ and_(t2, t2, Operand(t1));
279
280 // Scale the index by multiplying by the element size.
281 ASSERT(NumberDictionary::kEntrySize == 3);
282 __ add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3
283
284 // Check if the key is identical to the name.
285 __ add(t2, elements, Operand(t2, LSL, kPointerSizeLog2));
286 __ ldr(ip, FieldMemOperand(t2, NumberDictionary::kElementsStartOffset));
287 __ cmp(key, Operand(ip));
288 if (i != kProbes - 1) {
289 __ b(eq, &done);
290 } else {
291 __ b(ne, miss);
292 }
293 }
294
295 __ bind(&done);
296 // Check that the value is a normal property.
297 // t2: elements + (index * kPointerSize)
298 const int kDetailsOffset =
299 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
300 __ ldr(t1, FieldMemOperand(t2, kDetailsOffset));
301 __ tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::mask())));
302 __ b(ne, miss);
303
304 // Get the value at the masked, scaled index and return.
305 const int kValueOffset =
306 NumberDictionary::kElementsStartOffset + kPointerSize;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000307 __ ldr(result, FieldMemOperand(t2, kValueOffset));
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000308}
309
310
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000311void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
312 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000313 // -- r2 : name
314 // -- lr : return address
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000315 // -- r0 : receiver
316 // -- sp[0] : receiver
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000317 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000318 Label miss;
319
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000320 StubCompiler::GenerateLoadArrayLength(masm, r0, r3, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000321 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000322 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000323}
324
325
ager@chromium.org378b34e2011-01-28 08:04:38 +0000326void LoadIC::GenerateStringLength(MacroAssembler* masm, bool support_wrappers) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000327 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000328 // -- r2 : name
329 // -- lr : return address
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000330 // -- r0 : receiver
331 // -- sp[0] : receiver
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000332 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000333 Label miss;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000334
ager@chromium.org378b34e2011-01-28 08:04:38 +0000335 StubCompiler::GenerateLoadStringLength(masm, r0, r1, r3, &miss,
336 support_wrappers);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000337 // Cache miss: Jump to runtime.
338 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000339 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000340}
341
342
343void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
344 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000345 // -- r2 : name
346 // -- lr : return address
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000347 // -- r0 : receiver
348 // -- sp[0] : receiver
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000349 // -----------------------------------
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000350 Label miss;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000351
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000352 StubCompiler::GenerateLoadFunctionPrototype(masm, r0, r1, r3, &miss);
353 __ bind(&miss);
354 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000355}
356
357
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000358// Checks the receiver for special cases (value type, slow case bits).
359// Falls through for regular JS object.
360static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
361 Register receiver,
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000362 Register map,
363 Register scratch,
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000364 int interceptor_bit,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000365 Label* slow) {
366 // Check that the object isn't a smi.
ager@chromium.org378b34e2011-01-28 08:04:38 +0000367 __ JumpIfSmi(receiver, slow);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000368 // Get the map of the receiver.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000369 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000370 // Check bit field.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000371 __ ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset));
372 __ tst(scratch,
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000373 Operand((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)));
ager@chromium.org378b34e2011-01-28 08:04:38 +0000374 __ b(ne, slow);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000375 // Check that the object is some kind of JS object EXCEPT JS Value type.
376 // In the case that the object is a value-wrapper object,
377 // we enter the runtime system to make sure that indexing into string
378 // objects work as intended.
379 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000380 __ ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
381 __ cmp(scratch, Operand(JS_OBJECT_TYPE));
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000382 __ b(lt, slow);
383}
384
385
386// Loads an indexed element from a fast case array.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000387// If not_fast_array is NULL, doesn't perform the elements map check.
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000388static void GenerateFastArrayLoad(MacroAssembler* masm,
389 Register receiver,
390 Register key,
391 Register elements,
392 Register scratch1,
393 Register scratch2,
394 Register result,
395 Label* not_fast_array,
396 Label* out_of_range) {
397 // Register use:
398 //
399 // receiver - holds the receiver on entry.
400 // Unchanged unless 'result' is the same register.
401 //
402 // key - holds the smi key on entry.
403 // Unchanged unless 'result' is the same register.
404 //
405 // elements - holds the elements of the receiver on exit.
406 //
407 // result - holds the result on exit if the load succeeded.
408 // Allowed to be the the same as 'receiver' or 'key'.
409 // Unchanged on bailout so 'receiver' and 'key' can be safely
410 // used by further computation.
411 //
412 // Scratch registers:
413 //
414 // scratch1 - used to hold elements map and elements length.
415 // Holds the elements map if not_fast_array branch is taken.
416 //
417 // scratch2 - used to hold the loaded value.
418
419 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000420 if (not_fast_array != NULL) {
421 // Check that the object is in fast mode and writable.
422 __ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset));
423 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
424 __ cmp(scratch1, ip);
425 __ b(ne, not_fast_array);
426 } else {
427 __ AssertFastElements(elements);
428 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000429 // Check that the key (index) is within bounds.
430 __ ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset));
431 __ cmp(key, Operand(scratch1));
432 __ b(hs, out_of_range);
433 // Fast case: Do the load.
434 __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
435 // The key is a smi.
436 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
437 __ ldr(scratch2,
438 MemOperand(scratch1, key, LSL, kPointerSizeLog2 - kSmiTagSize));
439 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
440 __ cmp(scratch2, ip);
441 // In case the loaded value is the_hole we have to consult GetProperty
442 // to ensure the prototype chain is searched.
443 __ b(eq, out_of_range);
444 __ mov(result, scratch2);
445}
446
447
448// Checks whether a key is an array index string or a symbol string.
449// Falls through if a key is a symbol.
450static void GenerateKeyStringCheck(MacroAssembler* masm,
451 Register key,
452 Register map,
453 Register hash,
454 Label* index_string,
455 Label* not_symbol) {
456 // The key is not a smi.
457 // Is it a string?
458 __ CompareObjectType(key, map, hash, FIRST_NONSTRING_TYPE);
459 __ b(ge, not_symbol);
460
461 // Is the string an array index, with cached numeric value?
462 __ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset));
463 __ tst(hash, Operand(String::kContainsCachedArrayIndexMask));
464 __ b(eq, index_string);
465
466 // Is the string a symbol?
467 // map: key map
468 __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset));
469 ASSERT(kSymbolTag != 0);
470 __ tst(hash, Operand(kIsSymbolMask));
471 __ b(eq, not_symbol);
472}
473
474
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000475// Defined in ic.cc.
476Object* CallIC_Miss(Arguments args);
477
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000478// The generated code does not accept smi keys.
479// The generated code falls through if both probes miss.
480static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
481 int argc,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000482 Code::Kind kind,
483 Code::ExtraICState extra_ic_state) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000484 // ----------- S t a t e -------------
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000485 // -- r1 : receiver
ager@chromium.org5c838252010-02-19 08:53:10 +0000486 // -- r2 : name
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000487 // -----------------------------------
488 Label number, non_number, non_string, boolean, probe, miss;
489
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000490 // Probe the stub cache.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000491 Code::Flags flags = Code::ComputeFlags(kind,
492 NOT_IN_LOOP,
493 MONOMORPHIC,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000494 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000495 NORMAL,
496 argc);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000497 Isolate::Current()->stub_cache()->GenerateProbe(
498 masm, flags, r1, r2, r3, r4, r5);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000499
500 // If the stub cache probing failed, the receiver might be a value.
501 // For value objects, we use the map of the prototype objects for
502 // the corresponding JSValue for the cache and that is what we need
503 // to probe.
504 //
505 // Check for number.
506 __ tst(r1, Operand(kSmiTagMask));
507 __ b(eq, &number);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000508 __ CompareObjectType(r1, r3, r3, HEAP_NUMBER_TYPE);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000509 __ b(ne, &non_number);
510 __ bind(&number);
511 StubCompiler::GenerateLoadGlobalFunctionPrototype(
512 masm, Context::NUMBER_FUNCTION_INDEX, r1);
513 __ b(&probe);
514
515 // Check for string.
516 __ bind(&non_number);
517 __ cmp(r3, Operand(FIRST_NONSTRING_TYPE));
518 __ b(hs, &non_string);
519 StubCompiler::GenerateLoadGlobalFunctionPrototype(
520 masm, Context::STRING_FUNCTION_INDEX, r1);
521 __ b(&probe);
522
523 // Check for boolean.
524 __ bind(&non_string);
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000525 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
526 __ cmp(r1, ip);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000527 __ b(eq, &boolean);
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000528 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
529 __ cmp(r1, ip);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000530 __ b(ne, &miss);
531 __ bind(&boolean);
532 StubCompiler::GenerateLoadGlobalFunctionPrototype(
533 masm, Context::BOOLEAN_FUNCTION_INDEX, r1);
534
535 // Probe the stub cache for the value object.
536 __ bind(&probe);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000537 Isolate::Current()->stub_cache()->GenerateProbe(
538 masm, flags, r1, r2, r3, r4, r5);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000539
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000540 __ bind(&miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000541}
542
543
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000544static void GenerateFunctionTailCall(MacroAssembler* masm,
545 int argc,
546 Label* miss,
547 Register scratch) {
548 // r1: function
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000549
550 // Check that the value isn't a smi.
551 __ tst(r1, Operand(kSmiTagMask));
552 __ b(eq, miss);
553
554 // Check that the value is a JSFunction.
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000555 __ CompareObjectType(r1, scratch, scratch, JS_FUNCTION_TYPE);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000556 __ b(ne, miss);
557
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000558 // Invoke the function.
559 ParameterCount actual(argc);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000560 __ InvokeFunction(r1, actual, JUMP_FUNCTION,
561 NullCallWrapper(), CALL_AS_METHOD);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000562}
563
564
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000565static void GenerateCallNormal(MacroAssembler* masm, int argc) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000566 // ----------- S t a t e -------------
ager@chromium.org5c838252010-02-19 08:53:10 +0000567 // -- r2 : name
568 // -- lr : return address
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000569 // -----------------------------------
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000570 Label miss;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000571
mads.s.ager31e71382008-08-13 09:32:07 +0000572 // Get the receiver of the function from the stack into r1.
573 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000574
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000575 GenerateStringDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000576
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000577 // r0: elements
578 // Search the dictionary - put result in register r1.
579 GenerateDictionaryLoad(masm, &miss, r0, r2, r1, r3, r4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000581 GenerateFunctionTailCall(masm, argc, &miss, r4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000582
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000583 __ bind(&miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000584}
585
586
danno@chromium.org40cb8782011-05-25 07:58:50 +0000587static void GenerateCallMiss(MacroAssembler* masm,
588 int argc,
589 IC::UtilityId id,
590 Code::ExtraICState extra_ic_state) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000591 // ----------- S t a t e -------------
ager@chromium.org5c838252010-02-19 08:53:10 +0000592 // -- r2 : name
593 // -- lr : return address
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000594 // -----------------------------------
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000595 Isolate* isolate = masm->isolate();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000596
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000597 if (id == IC::kCallIC_Miss) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000598 __ IncrementCounter(isolate->counters()->call_miss(), 1, r3, r4);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000599 } else {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000600 __ IncrementCounter(isolate->counters()->keyed_call_miss(), 1, r3, r4);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000601 }
602
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000603 // Get the receiver of the function from the stack.
ager@chromium.org5c838252010-02-19 08:53:10 +0000604 __ ldr(r3, MemOperand(sp, argc * kPointerSize));
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000605
606 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000607
608 // Push the receiver and the name of the function.
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000609 __ Push(r3, r2);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000610
611 // Call the entry.
mads.s.ager31e71382008-08-13 09:32:07 +0000612 __ mov(r0, Operand(2));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000613 __ mov(r1, Operand(ExternalReference(IC_Utility(id), isolate)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000614
ager@chromium.orga1645e22009-09-09 19:27:10 +0000615 CEntryStub stub(1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000616 __ CallStub(&stub);
617
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000618 // Move result to r1 and leave the internal frame.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000619 __ mov(r1, Operand(r0));
ager@chromium.org236ad962008-09-25 09:45:57 +0000620 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000621
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000622 // Check if the receiver is a global object of some sort.
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000623 // This can happen only for regular CallIC but not KeyedCallIC.
624 if (id == IC::kCallIC_Miss) {
625 Label invoke, global;
626 __ ldr(r2, MemOperand(sp, argc * kPointerSize)); // receiver
627 __ tst(r2, Operand(kSmiTagMask));
628 __ b(eq, &invoke);
629 __ CompareObjectType(r2, r3, r3, JS_GLOBAL_OBJECT_TYPE);
630 __ b(eq, &global);
631 __ cmp(r3, Operand(JS_BUILTINS_OBJECT_TYPE));
632 __ b(ne, &invoke);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000633
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000634 // Patch the receiver on the stack.
635 __ bind(&global);
636 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
637 __ str(r2, MemOperand(sp, argc * kPointerSize));
638 __ bind(&invoke);
639 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000640
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000641 // Invoke the function.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000642 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
643 ? CALL_AS_FUNCTION
644 : CALL_AS_METHOD;
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000645 ParameterCount actual(argc);
danno@chromium.org40cb8782011-05-25 07:58:50 +0000646 __ InvokeFunction(r1,
647 actual,
648 JUMP_FUNCTION,
649 NullCallWrapper(),
650 call_kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000651}
652
653
danno@chromium.org40cb8782011-05-25 07:58:50 +0000654void CallIC::GenerateMiss(MacroAssembler* masm,
655 int argc,
656 Code::ExtraICState extra_ic_state) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000657 // ----------- S t a t e -------------
658 // -- r2 : name
659 // -- lr : return address
660 // -----------------------------------
661
danno@chromium.org40cb8782011-05-25 07:58:50 +0000662 GenerateCallMiss(masm, argc, IC::kCallIC_Miss, extra_ic_state);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000663}
664
665
danno@chromium.org40cb8782011-05-25 07:58:50 +0000666void CallIC::GenerateMegamorphic(MacroAssembler* masm,
667 int argc,
668 Code::ExtraICState extra_ic_state) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000669 // ----------- S t a t e -------------
670 // -- r2 : name
671 // -- lr : return address
672 // -----------------------------------
673
674 // Get the receiver of the function from the stack into r1.
675 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
danno@chromium.org40cb8782011-05-25 07:58:50 +0000676 GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, extra_ic_state);
677 GenerateMiss(masm, argc, extra_ic_state);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000678}
679
680
681void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
682 // ----------- S t a t e -------------
683 // -- r2 : name
684 // -- lr : return address
685 // -----------------------------------
686
687 GenerateCallNormal(masm, argc);
danno@chromium.org40cb8782011-05-25 07:58:50 +0000688 GenerateMiss(masm, argc, Code::kNoExtraICState);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000689}
690
691
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000692void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000693 // ----------- S t a t e -------------
694 // -- r2 : name
695 // -- lr : return address
696 // -----------------------------------
697
danno@chromium.org40cb8782011-05-25 07:58:50 +0000698 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss, Code::kNoExtraICState);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000699}
700
701
702void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000703 // ----------- S t a t e -------------
704 // -- r2 : name
705 // -- lr : return address
706 // -----------------------------------
707
708 // Get the receiver of the function from the stack into r1.
709 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
710
711 Label do_call, slow_call, slow_load, slow_reload_receiver;
712 Label check_number_dictionary, check_string, lookup_monomorphic_cache;
713 Label index_smi, index_string;
714
715 // Check that the key is a smi.
ager@chromium.org378b34e2011-01-28 08:04:38 +0000716 __ JumpIfNotSmi(r2, &check_string);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000717 __ bind(&index_smi);
718 // Now the key is known to be a smi. This place is also jumped to from below
719 // where a numeric string is converted to a smi.
720
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000721 GenerateKeyedLoadReceiverCheck(
722 masm, r1, r0, r3, Map::kHasIndexedInterceptor, &slow_call);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000723
724 GenerateFastArrayLoad(
725 masm, r1, r2, r4, r3, r0, r1, &check_number_dictionary, &slow_load);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000726 Counters* counters = masm->isolate()->counters();
727 __ IncrementCounter(counters->keyed_call_generic_smi_fast(), 1, r0, r3);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000728
729 __ bind(&do_call);
730 // receiver in r1 is not used after this point.
731 // r2: key
732 // r1: function
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000733 GenerateFunctionTailCall(masm, argc, &slow_call, r0);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000734
735 __ bind(&check_number_dictionary);
736 // r2: key
737 // r3: elements map
738 // r4: elements
739 // Check whether the elements is a number dictionary.
740 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
741 __ cmp(r3, ip);
742 __ b(ne, &slow_load);
743 __ mov(r0, Operand(r2, ASR, kSmiTagSize));
744 // r0: untagged index
745 GenerateNumberDictionaryLoad(masm, &slow_load, r4, r2, r1, r0, r3, r5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000746 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1, r0, r3);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000747 __ jmp(&do_call);
748
749 __ bind(&slow_load);
750 // This branch is taken when calling KeyedCallIC_Miss is neither required
751 // nor beneficial.
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000752 __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1, r0, r3);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000753 __ EnterInternalFrame();
754 __ push(r2); // save the key
755 __ Push(r1, r2); // pass the receiver and the key
756 __ CallRuntime(Runtime::kKeyedGetProperty, 2);
757 __ pop(r2); // restore the key
758 __ LeaveInternalFrame();
759 __ mov(r1, r0);
760 __ jmp(&do_call);
761
762 __ bind(&check_string);
763 GenerateKeyStringCheck(masm, r2, r0, r3, &index_string, &slow_call);
764
765 // The key is known to be a symbol.
766 // If the receiver is a regular JS object with slow properties then do
767 // a quick inline probe of the receiver's dictionary.
768 // Otherwise do the monomorphic cache probe.
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000769 GenerateKeyedLoadReceiverCheck(
770 masm, r1, r0, r3, Map::kHasNamedInterceptor, &lookup_monomorphic_cache);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000771
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000772 __ ldr(r0, FieldMemOperand(r1, JSObject::kPropertiesOffset));
773 __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000774 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
775 __ cmp(r3, ip);
776 __ b(ne, &lookup_monomorphic_cache);
777
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000778 GenerateDictionaryLoad(masm, &slow_load, r0, r2, r1, r3, r4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000779 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1, r0, r3);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000780 __ jmp(&do_call);
781
782 __ bind(&lookup_monomorphic_cache);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000783 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1, r0, r3);
danno@chromium.org40cb8782011-05-25 07:58:50 +0000784 GenerateMonomorphicCacheProbe(masm,
785 argc,
786 Code::KEYED_CALL_IC,
787 Code::kNoExtraICState);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000788 // Fall through on miss.
789
790 __ bind(&slow_call);
791 // This branch is taken if:
792 // - the receiver requires boxing or access check,
793 // - the key is neither smi nor symbol,
794 // - the value loaded is not a function,
795 // - there is hope that the runtime will create a monomorphic call stub
796 // that will get fetched next time.
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000797 __ IncrementCounter(counters->keyed_call_generic_slow(), 1, r0, r3);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000798 GenerateMiss(masm, argc);
799
800 __ bind(&index_string);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000801 __ IndexFromHash(r3, r2);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000802 // Now jump to the place where smi keys are handled.
803 __ jmp(&index_smi);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000804}
805
806
807void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000808 // ----------- S t a t e -------------
809 // -- r2 : name
810 // -- lr : return address
811 // -----------------------------------
812
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000813 // Check if the name is a string.
814 Label miss;
815 __ tst(r2, Operand(kSmiTagMask));
816 __ b(eq, &miss);
817 __ IsObjectJSStringType(r2, r0, &miss);
818
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000819 GenerateCallNormal(masm, argc);
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000820 __ bind(&miss);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000821 GenerateMiss(masm, argc);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000822}
823
824
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000825// Defined in ic.cc.
826Object* LoadIC_Miss(Arguments args);
827
828void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
829 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000830 // -- r2 : name
831 // -- lr : return address
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000832 // -- r0 : receiver
833 // -- sp[0] : receiver
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000834 // -----------------------------------
835
836 // Probe the stub cache.
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000837 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
838 NOT_IN_LOOP,
839 MONOMORPHIC);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000840 Isolate::Current()->stub_cache()->GenerateProbe(
841 masm, flags, r0, r2, r3, r4, r5);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000842
843 // Cache miss: Jump to runtime.
ager@chromium.org5c838252010-02-19 08:53:10 +0000844 GenerateMiss(masm);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000845}
846
847
848void LoadIC::GenerateNormal(MacroAssembler* masm) {
849 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000850 // -- r2 : name
851 // -- lr : return address
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000852 // -- r0 : receiver
853 // -- sp[0] : receiver
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000854 // -----------------------------------
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000855 Label miss;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000856
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000857 GenerateStringDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000858
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000859 // r1: elements
860 GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000861 __ Ret();
862
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000863 // Cache miss: Jump to runtime.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000864 __ bind(&miss);
ager@chromium.org5c838252010-02-19 08:53:10 +0000865 GenerateMiss(masm);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000866}
867
868
869void LoadIC::GenerateMiss(MacroAssembler* masm) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000870 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000871 // -- r2 : name
872 // -- lr : return address
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000873 // -- r0 : receiver
874 // -- sp[0] : receiver
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000875 // -----------------------------------
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000876 Isolate* isolate = masm->isolate();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000877
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000878 __ IncrementCounter(isolate->counters()->load_miss(), 1, r3, r4);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000879
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000880 __ mov(r3, r0);
881 __ Push(r3, r2);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000882
mads.s.ager31e71382008-08-13 09:32:07 +0000883 // Perform tail call to the entry.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000884 ExternalReference ref =
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000885 ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000886 __ TailCallExternalReference(ref, 2, 1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000887}
888
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000889
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000890void KeyedLoadIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000891 // ---------- S t a t e --------------
892 // -- lr : return address
ager@chromium.orgac091b72010-05-05 07:34:42 +0000893 // -- r0 : key
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000894 // -- r1 : receiver
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000895 // -----------------------------------
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000896 Isolate* isolate = masm->isolate();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000897
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000898 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r3, r4);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000899
ager@chromium.orgac091b72010-05-05 07:34:42 +0000900 __ Push(r1, r0);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000901
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000902 // Perform tail call to the entry.
903 ExternalReference ref = force_generic
904 ? ExternalReference(IC_Utility(kKeyedLoadIC_MissForceGeneric), isolate)
905 : ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate);
906
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000907 __ TailCallExternalReference(ref, 2, 1);
ager@chromium.org5c838252010-02-19 08:53:10 +0000908}
909
910
911void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
912 // ---------- S t a t e --------------
913 // -- lr : return address
ager@chromium.orgac091b72010-05-05 07:34:42 +0000914 // -- r0 : key
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000915 // -- r1 : receiver
ager@chromium.org5c838252010-02-19 08:53:10 +0000916 // -----------------------------------
917
ager@chromium.orgac091b72010-05-05 07:34:42 +0000918 __ Push(r1, r0);
ager@chromium.org5c838252010-02-19 08:53:10 +0000919
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000920 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000921}
922
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000923
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000924void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000925 // ---------- S t a t e --------------
926 // -- lr : return address
ager@chromium.orgac091b72010-05-05 07:34:42 +0000927 // -- r0 : key
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000928 // -- r1 : receiver
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000929 // -----------------------------------
lrn@chromium.orgc4e51ac2010-08-09 09:47:21 +0000930 Label slow, check_string, index_smi, index_string, property_array_property;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000931 Label probe_dictionary, check_number_dictionary;
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000932
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000933 Register key = r0;
934 Register receiver = r1;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000935
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000936 Isolate* isolate = masm->isolate();
937
ager@chromium.org5c838252010-02-19 08:53:10 +0000938 // Check that the key is a smi.
ager@chromium.org378b34e2011-01-28 08:04:38 +0000939 __ JumpIfNotSmi(key, &check_string);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000940 __ bind(&index_smi);
941 // Now the key is known to be a smi. This place is also jumped to from below
942 // where a numeric string is converted to a smi.
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000943
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000944 GenerateKeyedLoadReceiverCheck(
945 masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow);
946
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000947 // Check the receiver's map to see if it has fast elements.
948 __ CheckFastElements(r2, r3, &check_number_dictionary);
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000949
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000950 GenerateFastArrayLoad(
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000951 masm, receiver, key, r4, r3, r2, r0, NULL, &slow);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000952 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r2, r3);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000953 __ Ret();
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000954
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000955 __ bind(&check_number_dictionary);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000956 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
957 __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset));
958
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000959 // Check whether the elements is a number dictionary.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000960 // r0: key
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000961 // r3: elements map
962 // r4: elements
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000963 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
964 __ cmp(r3, ip);
965 __ b(ne, &slow);
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000966 __ mov(r2, Operand(r0, ASR, kSmiTagSize));
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000967 GenerateNumberDictionaryLoad(masm, &slow, r4, r0, r0, r2, r3, r5);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000968 __ Ret();
969
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000970 // Slow case, key and receiver still in r0 and r1.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000971 __ bind(&slow);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000972 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(),
973 1, r2, r3);
ager@chromium.org5c838252010-02-19 08:53:10 +0000974 GenerateRuntimeGetProperty(masm);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000975
976 __ bind(&check_string);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000977 GenerateKeyStringCheck(masm, key, r2, r3, &index_string, &slow);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000978
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000979 GenerateKeyedLoadReceiverCheck(
980 masm, receiver, r2, r3, Map::kHasNamedInterceptor, &slow);
981
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000982 // If the receiver is a fast-case object, check the keyed lookup
983 // cache. Otherwise probe the dictionary.
984 __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset));
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000985 __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000986 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000987 __ cmp(r4, ip);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000988 __ b(eq, &probe_dictionary);
989
990 // Load the map of the receiver, compute the keyed lookup cache hash
991 // based on 32 bits of the map pointer and the string hash.
992 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
993 __ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift));
994 __ ldr(r4, FieldMemOperand(r0, String::kHashFieldOffset));
995 __ eor(r3, r3, Operand(r4, ASR, String::kHashShift));
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000996 __ And(r3, r3, Operand(KeyedLookupCache::kCapacityMask));
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000997
998 // Load the key (consisting of map and symbol) from the cache and
999 // check for match.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001000 ExternalReference cache_keys =
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001001 ExternalReference::keyed_lookup_cache_keys(isolate);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +00001002 __ mov(r4, Operand(cache_keys));
1003 __ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1));
1004 __ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); // Move r4 to symbol.
1005 __ cmp(r2, r5);
1006 __ b(ne, &slow);
1007 __ ldr(r5, MemOperand(r4));
1008 __ cmp(r0, r5);
1009 __ b(ne, &slow);
1010
lrn@chromium.orgc4e51ac2010-08-09 09:47:21 +00001011 // Get field offset.
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +00001012 // r0 : key
1013 // r1 : receiver
1014 // r2 : receiver's map
1015 // r3 : lookup cache index
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001016 ExternalReference cache_field_offsets =
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001017 ExternalReference::keyed_lookup_cache_field_offsets(isolate);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +00001018 __ mov(r4, Operand(cache_field_offsets));
1019 __ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2));
1020 __ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset));
lrn@chromium.orgc4e51ac2010-08-09 09:47:21 +00001021 __ sub(r5, r5, r6, SetCC);
1022 __ b(ge, &property_array_property);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +00001023
1024 // Load in-object property.
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +00001025 __ ldrb(r6, FieldMemOperand(r2, Map::kInstanceSizeOffset));
1026 __ add(r6, r6, r5); // Index from start of object.
1027 __ sub(r1, r1, Operand(kHeapObjectTag)); // Remove the heap tag.
1028 __ ldr(r0, MemOperand(r1, r6, LSL, kPointerSizeLog2));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001029 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
1030 1, r2, r3);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +00001031 __ Ret();
1032
lrn@chromium.orgc4e51ac2010-08-09 09:47:21 +00001033 // Load property array property.
1034 __ bind(&property_array_property);
1035 __ ldr(r1, FieldMemOperand(r1, JSObject::kPropertiesOffset));
1036 __ add(r1, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1037 __ ldr(r0, MemOperand(r1, r5, LSL, kPointerSizeLog2));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001038 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
1039 1, r2, r3);
lrn@chromium.orgc4e51ac2010-08-09 09:47:21 +00001040 __ Ret();
1041
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +00001042 // Do a quick inline probe of the receiver's dictionary, if it
1043 // exists.
1044 __ bind(&probe_dictionary);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001045 // r1: receiver
1046 // r0: key
1047 // r3: elements
1048 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
1049 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
1050 GenerateGlobalInstanceTypeCheck(masm, r2, &slow);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +00001051 // Load the property to r0.
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001052 GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001053 __ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(),
1054 1, r2, r3);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +00001055 __ Ret();
1056
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +00001057 __ bind(&index_string);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001058 __ IndexFromHash(r3, key);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +00001059 // Now jump to the place where smi keys are handled.
1060 __ jmp(&index_smi);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001061}
1062
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001063
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00001064void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
1065 // ---------- S t a t e --------------
1066 // -- lr : return address
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001067 // -- r0 : key (index)
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001068 // -- r1 : receiver
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001069 // -----------------------------------
ager@chromium.orgac091b72010-05-05 07:34:42 +00001070 Label miss;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001071
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001072 Register receiver = r1;
ager@chromium.orgac091b72010-05-05 07:34:42 +00001073 Register index = r0;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001074 Register scratch1 = r2;
1075 Register scratch2 = r3;
1076 Register result = r0;
ager@chromium.org357bf652010-04-12 11:30:10 +00001077
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001078 StringCharAtGenerator char_at_generator(receiver,
1079 index,
1080 scratch1,
1081 scratch2,
1082 result,
1083 &miss, // When not a string.
1084 &miss, // When not a number.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001085 &miss, // When index out of range.
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001086 STRING_INDEX_IS_ARRAY_INDEX);
1087 char_at_generator.GenerateFast(masm);
1088 __ Ret();
ager@chromium.org357bf652010-04-12 11:30:10 +00001089
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001090 StubRuntimeCallHelper call_helper;
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001091 char_at_generator.GenerateSlow(masm, call_helper);
ager@chromium.org357bf652010-04-12 11:30:10 +00001092
ager@chromium.org357bf652010-04-12 11:30:10 +00001093 __ bind(&miss);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001094 GenerateMiss(masm, false);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00001095}
1096
1097
ager@chromium.org5c838252010-02-19 08:53:10 +00001098void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
1099 // ---------- S t a t e --------------
1100 // -- lr : return address
ager@chromium.orgac091b72010-05-05 07:34:42 +00001101 // -- r0 : key
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001102 // -- r1 : receiver
ager@chromium.org5c838252010-02-19 08:53:10 +00001103 // -----------------------------------
1104 Label slow;
1105
ager@chromium.org5c838252010-02-19 08:53:10 +00001106 // Check that the receiver isn't a smi.
ager@chromium.org378b34e2011-01-28 08:04:38 +00001107 __ JumpIfSmi(r1, &slow);
ager@chromium.org5c838252010-02-19 08:53:10 +00001108
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00001109 // Check that the key is an array index, that is Uint32.
1110 __ tst(r0, Operand(kSmiTagMask | kSmiSignMask));
1111 __ b(ne, &slow);
ager@chromium.org5c838252010-02-19 08:53:10 +00001112
1113 // Get the map of the receiver.
1114 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
1115
1116 // Check that it has indexed interceptor and access checks
1117 // are not enabled for this object.
1118 __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
1119 __ and_(r3, r3, Operand(kSlowCaseBitFieldMask));
1120 __ cmp(r3, Operand(1 << Map::kHasIndexedInterceptor));
1121 __ b(ne, &slow);
1122
1123 // Everything is fine, call runtime.
lrn@chromium.orgc34f5802010-04-28 12:53:43 +00001124 __ Push(r1, r0); // Receiver, key.
ager@chromium.org5c838252010-02-19 08:53:10 +00001125
1126 // Perform tail call to the entry.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001127 __ TailCallExternalReference(
1128 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor),
1129 masm->isolate()),
1130 2,
1131 1);
ager@chromium.org5c838252010-02-19 08:53:10 +00001132
1133 __ bind(&slow);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001134 GenerateMiss(masm, false);
ager@chromium.org5c838252010-02-19 08:53:10 +00001135}
1136
1137
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001138void KeyedStoreIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001139 // ---------- S t a t e --------------
1140 // -- r0 : value
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001141 // -- r1 : key
1142 // -- r2 : receiver
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001143 // -- lr : return address
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001144 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001145
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001146 // Push receiver, key and value for runtime call.
1147 __ Push(r2, r1, r0);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001148
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001149 ExternalReference ref = force_generic
1150 ? ExternalReference(IC_Utility(kKeyedStoreIC_MissForceGeneric),
1151 masm->isolate())
1152 : ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
1153 __ TailCallExternalReference(ref, 3, 1);
1154}
1155
1156
1157void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
1158 // ---------- S t a t e --------------
1159 // -- r0 : value
1160 // -- r1 : key
1161 // -- r2 : receiver
1162 // -- lr : return address
1163 // -----------------------------------
1164
1165 // Push receiver, key and value for runtime call.
1166 __ Push(r2, r1, r0);
1167
1168 // The slow case calls into the runtime to complete the store without causing
1169 // an IC miss that would otherwise cause a transition to the generic stub.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001170 ExternalReference ref =
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001171 ExternalReference(IC_Utility(kKeyedStoreIC_Slow), masm->isolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001172 __ TailCallExternalReference(ref, 3, 1);
ager@chromium.org5c838252010-02-19 08:53:10 +00001173}
1174
1175
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001176void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
1177 StrictModeFlag strict_mode) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001178 // ---------- S t a t e --------------
1179 // -- r0 : value
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001180 // -- r1 : key
1181 // -- r2 : receiver
ager@chromium.org5c838252010-02-19 08:53:10 +00001182 // -- lr : return address
ager@chromium.org5c838252010-02-19 08:53:10 +00001183 // -----------------------------------
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001184
1185 // Push receiver, key and value for runtime call.
1186 __ Push(r2, r1, r0);
ager@chromium.org5c838252010-02-19 08:53:10 +00001187
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001188 __ mov(r1, Operand(Smi::FromInt(NONE))); // PropertyAttributes
1189 __ mov(r0, Operand(Smi::FromInt(strict_mode))); // Strict mode.
1190 __ Push(r1, r0);
1191
1192 __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001193}
1194
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001195
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001196void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
1197 StrictModeFlag strict_mode) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001198 // ---------- S t a t e --------------
1199 // -- r0 : value
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001200 // -- r1 : key
1201 // -- r2 : receiver
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001202 // -- lr : return address
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001203 // -----------------------------------
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001204 Label slow, fast, array, extra;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001205
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001206 // Register usage.
1207 Register value = r0;
1208 Register key = r1;
1209 Register receiver = r2;
1210 Register elements = r3; // Elements array of the receiver.
1211 // r4 and r5 are used as general scratch registers.
1212
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001213 // Check that the key is a smi.
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001214 __ tst(key, Operand(kSmiTagMask));
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001215 __ b(ne, &slow);
1216 // Check that the object isn't a smi.
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001217 __ tst(receiver, Operand(kSmiTagMask));
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001218 __ b(eq, &slow);
ager@chromium.org8bb60582008-12-11 12:02:20 +00001219 // Get the map of the object.
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001220 __ ldr(r4, FieldMemOperand(receiver, HeapObject::kMapOffset));
ager@chromium.org8bb60582008-12-11 12:02:20 +00001221 // Check that the receiver does not require access checks. We need
1222 // to do this because this generic stub does not perform map checks.
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001223 __ ldrb(ip, FieldMemOperand(r4, Map::kBitFieldOffset));
ager@chromium.org8bb60582008-12-11 12:02:20 +00001224 __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded));
1225 __ b(ne, &slow);
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001226 // Check if the object is a JS array or not.
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001227 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
1228 __ cmp(r4, Operand(JS_ARRAY_TYPE));
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001229 __ b(eq, &array);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001230 // Check that the object is some kind of JSObject.
1231 __ cmp(r4, Operand(FIRST_JS_RECEIVER_TYPE));
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001232 __ b(lt, &slow);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001233 __ cmp(r4, Operand(JS_PROXY_TYPE));
1234 __ b(eq, &slow);
1235 __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE));
1236 __ b(eq, &slow);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001237
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001238 // Object case: Check key against length in the elements array.
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001239 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001240 // Check that the object is in fast mode and writable.
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001241 __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset));
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001242 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001243 __ cmp(r4, ip);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001244 __ b(ne, &slow);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001245 // Check array bounds. Both the key and the length of FixedArray are smis.
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001246 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset));
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001247 __ cmp(key, Operand(ip));
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001248 __ b(lo, &fast);
1249
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001250 // Slow case, handle jump to runtime.
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001251 __ bind(&slow);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001252 // Entry registers are intact.
1253 // r0: value.
1254 // r1: key.
1255 // r2: receiver.
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001256 GenerateRuntimeSetProperty(masm, strict_mode);
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001257
1258 // Extra capacity case: Check if there is extra capacity to
1259 // perform the store and update the length. Used for adding one
1260 // element to the array by writing to array[array.length].
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001261 __ bind(&extra);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001262 // Condition code from comparing key and array length is still available.
1263 __ b(ne, &slow); // Only support writing to writing to array[array.length].
1264 // Check for room in the elements backing store.
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001265 // Both the key and the length of FixedArray are smis.
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001266 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset));
ricow@chromium.org30ce4112010-05-31 10:38:25 +00001267 __ cmp(key, Operand(ip));
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001268 __ b(hs, &slow);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001269 // Calculate key + 1 as smi.
1270 ASSERT_EQ(0, kSmiTag);
1271 __ add(r4, key, Operand(Smi::FromInt(1)));
1272 __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001273 __ b(&fast);
1274
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001275 // Array case: Get the length and the elements array from the JS
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001276 // array. Check that the array is in fast mode (and writable); if it
1277 // is the length is always a smi.
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001278 __ bind(&array);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001279 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
1280 __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset));
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001281 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001282 __ cmp(r4, ip);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001283 __ b(ne, &slow);
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001284
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001285 // Check the key against the length in the array.
1286 __ ldr(ip, FieldMemOperand(receiver, JSArray::kLengthOffset));
1287 __ cmp(key, Operand(ip));
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001288 __ b(hs, &extra);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001289 // Fall through to fast case.
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001290
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001291 __ bind(&fast);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001292 // Fast case, store the value to the elements backing store.
1293 __ add(r5, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1294 __ add(r5, r5, Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize));
1295 __ str(value, MemOperand(r5));
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001296 // Skip write barrier if the written value is a smi.
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001297 __ tst(value, Operand(kSmiTagMask));
1298 __ Ret(eq);
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001299 // Update write barrier for the elements array address.
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001300 __ sub(r4, r5, Operand(elements));
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +00001301 __ RecordWrite(elements, Operand(r4), r5, r6);
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001302
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001303 __ Ret();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001304}
1305
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001306
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001307void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001308 StrictModeFlag strict_mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001309 // ----------- S t a t e -------------
1310 // -- r0 : value
ager@chromium.org5c838252010-02-19 08:53:10 +00001311 // -- r1 : receiver
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001312 // -- r2 : name
1313 // -- lr : return address
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001314 // -----------------------------------
1315
1316 // Get the receiver from the stack and probe the stub cache.
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001317 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
1318 NOT_IN_LOOP,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001319 MONOMORPHIC,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001320 strict_mode);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001321
1322 Isolate::Current()->stub_cache()->GenerateProbe(
1323 masm, flags, r1, r2, r3, r4, r5);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001324
1325 // Cache miss: Jump to runtime.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001326 GenerateMiss(masm);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001327}
1328
1329
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001330void StoreIC::GenerateMiss(MacroAssembler* masm) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001331 // ----------- S t a t e -------------
1332 // -- r0 : value
ager@chromium.org5c838252010-02-19 08:53:10 +00001333 // -- r1 : receiver
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001334 // -- r2 : name
1335 // -- lr : return address
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001336 // -----------------------------------
1337
lrn@chromium.orgc34f5802010-04-28 12:53:43 +00001338 __ Push(r1, r2, r0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001339
mads.s.ager31e71382008-08-13 09:32:07 +00001340 // Perform tail call to the entry.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001341 ExternalReference ref =
1342 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001343 __ TailCallExternalReference(ref, 3, 1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001344}
1345
1346
ager@chromium.org5c838252010-02-19 08:53:10 +00001347void StoreIC::GenerateArrayLength(MacroAssembler* masm) {
1348 // ----------- S t a t e -------------
1349 // -- r0 : value
1350 // -- r1 : receiver
1351 // -- r2 : name
1352 // -- lr : return address
1353 // -----------------------------------
1354 //
1355 // This accepts as a receiver anything JSObject::SetElementsLength accepts
1356 // (currently anything except for external and pixel arrays which means
1357 // anything with elements of FixedArray type.), but currently is restricted
1358 // to JSArray.
1359 // Value must be a number, but only smis are accepted as the most common case.
1360
1361 Label miss;
1362
1363 Register receiver = r1;
1364 Register value = r0;
1365 Register scratch = r3;
1366
1367 // Check that the receiver isn't a smi.
ager@chromium.org378b34e2011-01-28 08:04:38 +00001368 __ JumpIfSmi(receiver, &miss);
ager@chromium.org5c838252010-02-19 08:53:10 +00001369
1370 // Check that the object is a JS array.
1371 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
1372 __ b(ne, &miss);
1373
1374 // Check that elements are FixedArray.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001375 // We rely on StoreIC_ArrayLength below to deal with all types of
1376 // fast elements (including COW).
ager@chromium.org5c838252010-02-19 08:53:10 +00001377 __ ldr(scratch, FieldMemOperand(receiver, JSArray::kElementsOffset));
1378 __ CompareObjectType(scratch, scratch, scratch, FIXED_ARRAY_TYPE);
1379 __ b(ne, &miss);
1380
1381 // Check that value is a smi.
ager@chromium.org378b34e2011-01-28 08:04:38 +00001382 __ JumpIfNotSmi(value, &miss);
ager@chromium.org5c838252010-02-19 08:53:10 +00001383
1384 // Prepare tail call to StoreIC_ArrayLength.
lrn@chromium.orgc34f5802010-04-28 12:53:43 +00001385 __ Push(receiver, value);
ager@chromium.org5c838252010-02-19 08:53:10 +00001386
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001387 ExternalReference ref =
1388 ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001389 __ TailCallExternalReference(ref, 2, 1);
ager@chromium.org5c838252010-02-19 08:53:10 +00001390
1391 __ bind(&miss);
1392
1393 GenerateMiss(masm);
1394}
1395
1396
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001397void StoreIC::GenerateNormal(MacroAssembler* masm) {
1398 // ----------- S t a t e -------------
1399 // -- r0 : value
1400 // -- r1 : receiver
1401 // -- r2 : name
1402 // -- lr : return address
1403 // -----------------------------------
1404 Label miss;
1405
1406 GenerateStringDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss);
1407
1408 GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001409 Counters* counters = masm->isolate()->counters();
1410 __ IncrementCounter(counters->store_normal_hit(),
1411 1, r4, r5);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001412 __ Ret();
1413
1414 __ bind(&miss);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001415 __ IncrementCounter(counters->store_normal_miss(), 1, r4, r5);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001416 GenerateMiss(masm);
1417}
1418
1419
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001420void StoreIC::GenerateGlobalProxy(MacroAssembler* masm,
1421 StrictModeFlag strict_mode) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001422 // ----------- S t a t e -------------
1423 // -- r0 : value
1424 // -- r1 : receiver
1425 // -- r2 : name
1426 // -- lr : return address
1427 // -----------------------------------
1428
1429 __ Push(r1, r2, r0);
1430
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001431 __ mov(r1, Operand(Smi::FromInt(NONE))); // PropertyAttributes
1432 __ mov(r0, Operand(Smi::FromInt(strict_mode)));
1433 __ Push(r1, r0);
1434
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001435 // Do tail-call to runtime routine.
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001436 __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001437}
1438
1439
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001440#undef __
1441
1442
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001443Condition CompareIC::ComputeCondition(Token::Value op) {
1444 switch (op) {
1445 case Token::EQ_STRICT:
1446 case Token::EQ:
1447 return eq;
1448 case Token::LT:
1449 return lt;
1450 case Token::GT:
1451 // Reverse left and right operands to obtain ECMA-262 conversion order.
1452 return lt;
1453 case Token::LTE:
1454 // Reverse left and right operands to obtain ECMA-262 conversion order.
1455 return ge;
1456 case Token::GTE:
1457 return ge;
1458 default:
1459 UNREACHABLE();
ager@chromium.org378b34e2011-01-28 08:04:38 +00001460 return kNoCondition;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001461 }
1462}
1463
1464
1465void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
1466 HandleScope scope;
1467 Handle<Code> rewritten;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001468 State previous_state = GetState();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001469 State state = TargetState(previous_state, false, x, y);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001470 if (state == GENERIC) {
1471 CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS, r1, r0);
1472 rewritten = stub.GetCode();
1473 } else {
1474 ICCompareStub stub(op_, state);
1475 rewritten = stub.GetCode();
1476 }
1477 set_target(*rewritten);
1478
1479#ifdef DEBUG
1480 if (FLAG_trace_ic) {
1481 PrintF("[CompareIC (%s->%s)#%s]\n",
1482 GetStateName(previous_state),
1483 GetStateName(state),
1484 Token::Name(op_));
1485 }
1486#endif
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001487
1488 // Activate inlined smi code.
1489 if (previous_state == UNINITIALIZED) {
1490 PatchInlinedSmiCode(address());
1491 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001492}
1493
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001494
1495void PatchInlinedSmiCode(Address address) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001496 Address cmp_instruction_address =
1497 address + Assembler::kCallTargetAddressOffset;
1498
1499 // If the instruction following the call is not a cmp rx, #yyy, nothing
1500 // was inlined.
1501 Instr instr = Assembler::instr_at(cmp_instruction_address);
1502 if (!Assembler::IsCmpImmediate(instr)) {
1503 return;
1504 }
1505
1506 // The delta to the start of the map check instruction and the
1507 // condition code uses at the patched jump.
1508 int delta = Assembler::GetCmpImmediateRawImmediate(instr);
1509 delta +=
1510 Assembler::GetCmpImmediateRegister(instr).code() * kOff12Mask;
1511 // If the delta is 0 the instruction is cmp r0, #0 which also signals that
1512 // nothing was inlined.
1513 if (delta == 0) {
1514 return;
1515 }
1516
1517#ifdef DEBUG
1518 if (FLAG_trace_ic) {
1519 PrintF("[ patching ic at %p, cmp=%p, delta=%d\n",
1520 address, cmp_instruction_address, delta);
1521 }
1522#endif
1523
1524 Address patch_address =
1525 cmp_instruction_address - delta * Instruction::kInstrSize;
1526 Instr instr_at_patch = Assembler::instr_at(patch_address);
1527 Instr branch_instr =
1528 Assembler::instr_at(patch_address + Instruction::kInstrSize);
1529 ASSERT(Assembler::IsCmpRegister(instr_at_patch));
1530 ASSERT_EQ(Assembler::GetRn(instr_at_patch).code(),
1531 Assembler::GetRm(instr_at_patch).code());
1532 ASSERT(Assembler::IsBranch(branch_instr));
1533 if (Assembler::GetCondition(branch_instr) == eq) {
1534 // This is patching a "jump if not smi" site to be active.
1535 // Changing
1536 // cmp rx, rx
1537 // b eq, <target>
1538 // to
1539 // tst rx, #kSmiTagMask
1540 // b ne, <target>
1541 CodePatcher patcher(patch_address, 2);
1542 Register reg = Assembler::GetRn(instr_at_patch);
1543 patcher.masm()->tst(reg, Operand(kSmiTagMask));
1544 patcher.EmitCondition(ne);
1545 } else {
1546 ASSERT(Assembler::GetCondition(branch_instr) == ne);
1547 // This is patching a "jump if smi" site to be active.
1548 // Changing
1549 // cmp rx, rx
1550 // b ne, <target>
1551 // to
1552 // tst rx, #kSmiTagMask
1553 // b eq, <target>
1554 CodePatcher patcher(patch_address, 2);
1555 Register reg = Assembler::GetRn(instr_at_patch);
1556 patcher.masm()->tst(reg, Operand(kSmiTagMask));
1557 patcher.EmitCondition(eq);
1558 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001559}
1560
1561
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001562} } // namespace v8::internal
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001563
1564#endif // V8_TARGET_ARCH_ARM