Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(488)

Side by Side Diff: src/arm/ic-arm.cc

Issue 1751019: Change the LoadIC calling convention so that the receiver... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 // t0 - used to hold the property dictionary. 54 // t0 - used to hold the property dictionary.
55 // 55 //
56 // t1 - initially the receiver 56 // t1 - initially the receiver
57 // - used for the index into the property dictionary 57 // - used for the index into the property dictionary
58 // - holds the result on exit. 58 // - holds the result on exit.
59 // 59 //
60 // r3 - used as temporary and to hold the capacity of the property 60 // r3 - used as temporary and to hold the capacity of the property
61 // dictionary. 61 // dictionary.
62 // 62 //
63 // r2 - holds the name of the property and is unchanged. 63 // r2 - holds the name of the property and is unchanged.
64 // r4 - used as temporary.
64 65
65 Label done; 66 Label done;
66 67
67 // Check for the absence of an interceptor. 68 // Check for the absence of an interceptor.
68 // Load the map into t0. 69 // Load the map into t0.
69 __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset)); 70 __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset));
70 71
71 // Bail out if the receiver has a named interceptor. 72 // Bail out if the receiver has a named interceptor.
72 __ ldrb(r3, FieldMemOperand(t0, Map::kBitFieldOffset)); 73 __ ldrb(r3, FieldMemOperand(t0, Map::kBitFieldOffset));
73 __ tst(r3, Operand(1 << Map::kHasNamedInterceptor)); 74 __ tst(r3, Operand(1 << Map::kHasNamedInterceptor));
(...skipping 27 matching lines...) Expand all
101 102
102 const int kElementsStartOffset = StringDictionary::kHeaderSize + 103 const int kElementsStartOffset = StringDictionary::kHeaderSize +
103 StringDictionary::kElementsStartIndex * kPointerSize; 104 StringDictionary::kElementsStartIndex * kPointerSize;
104 105
105 // Generate an unrolled loop that performs a few probes before 106 // Generate an unrolled loop that performs a few probes before
106 // giving up. Measurements done on Gmail indicate that 2 probes 107 // giving up. Measurements done on Gmail indicate that 2 probes
107 // cover ~93% of loads from dictionaries. 108 // cover ~93% of loads from dictionaries.
108 static const int kProbes = 4; 109 static const int kProbes = 4;
109 for (int i = 0; i < kProbes; i++) { 110 for (int i = 0; i < kProbes; i++) {
110 // Compute the masked index: (hash + i + i * i) & mask. 111 // Compute the masked index: (hash + i + i * i) & mask.
111 __ ldr(t1, FieldMemOperand(r2, String::kHashFieldOffset)); 112 __ ldr(r4, FieldMemOperand(r2, String::kHashFieldOffset));
112 if (i > 0) { 113 if (i > 0) {
113 // Add the probe offset (i + i * i) left shifted to avoid right shifting 114 // Add the probe offset (i + i * i) left shifted to avoid right shifting
114 // the hash in a separate instruction. The value hash + i + i * i is right 115 // the hash in a separate instruction. The value hash + i + i * i is right
115 // shifted in the following and instruction. 116 // shifted in the following and instruction.
116 ASSERT(StringDictionary::GetProbeOffset(i) < 117 ASSERT(StringDictionary::GetProbeOffset(i) <
117 1 << (32 - String::kHashFieldOffset)); 118 1 << (32 - String::kHashFieldOffset));
118 __ add(t1, t1, Operand( 119 __ add(r4, r4, Operand(
119 StringDictionary::GetProbeOffset(i) << String::kHashShift)); 120 StringDictionary::GetProbeOffset(i) << String::kHashShift));
120 } 121 }
121 __ and_(t1, r3, Operand(t1, LSR, String::kHashShift)); 122 __ and_(r4, r3, Operand(r4, LSR, String::kHashShift));
122 123
123 // Scale the index by multiplying by the element size. 124 // Scale the index by multiplying by the element size.
124 ASSERT(StringDictionary::kEntrySize == 3); 125 ASSERT(StringDictionary::kEntrySize == 3);
125 __ add(t1, t1, Operand(t1, LSL, 1)); // t1 = t1 * 3 126 __ add(r4, r4, Operand(r4, LSL, 1)); // r4 = r4 * 3
126 127
127 // Check if the key is identical to the name. 128 // Check if the key is identical to the name.
128 __ add(t1, t0, Operand(t1, LSL, 2)); 129 __ add(r4, t0, Operand(r4, LSL, 2));
129 __ ldr(ip, FieldMemOperand(t1, kElementsStartOffset)); 130 __ ldr(ip, FieldMemOperand(r4, kElementsStartOffset));
130 __ cmp(r2, Operand(ip)); 131 __ cmp(r2, Operand(ip));
131 if (i != kProbes - 1) { 132 if (i != kProbes - 1) {
132 __ b(eq, &done); 133 __ b(eq, &done);
133 } else { 134 } else {
134 __ b(ne, miss); 135 __ b(ne, miss);
135 } 136 }
136 } 137 }
137 138
138 // Check that the value is a normal property. 139 // Check that the value is a normal property.
139 __ bind(&done); // t1 == t0 + 4*index 140 __ bind(&done); // r4 == t0 + 4*index
140 __ ldr(r3, FieldMemOperand(t1, kElementsStartOffset + 2 * kPointerSize)); 141 __ ldr(r3, FieldMemOperand(r4, kElementsStartOffset + 2 * kPointerSize));
141 __ tst(r3, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize)); 142 __ tst(r3, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize));
142 __ b(ne, miss); 143 __ b(ne, miss);
143 144
144 // Get the value at the masked, scaled index and return. 145 // Get the value at the masked, scaled index and return.
145 __ ldr(t1, FieldMemOperand(t1, kElementsStartOffset + 1 * kPointerSize)); 146 __ ldr(t1, FieldMemOperand(r4, kElementsStartOffset + 1 * kPointerSize));
146 } 147 }
147 148
148 149
149 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, 150 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
150 Label* miss, 151 Label* miss,
151 Register elements, 152 Register elements,
152 Register key, 153 Register key,
153 Register t0, 154 Register t0,
154 Register t1, 155 Register t1,
155 Register t2) { 156 Register t2) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 const int kValueOffset = 233 const int kValueOffset =
233 NumberDictionary::kElementsStartOffset + kPointerSize; 234 NumberDictionary::kElementsStartOffset + kPointerSize;
234 __ ldr(t0, FieldMemOperand(t2, kValueOffset)); 235 __ ldr(t0, FieldMemOperand(t2, kValueOffset));
235 } 236 }
236 237
237 238
238 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { 239 void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
239 // ----------- S t a t e ------------- 240 // ----------- S t a t e -------------
240 // -- r2 : name 241 // -- r2 : name
241 // -- lr : return address 242 // -- lr : return address
242 // -- [sp] : receiver 243 // -- r0 : receiver
244 // -- sp[0] : receiver
243 // ----------------------------------- 245 // -----------------------------------
244 Label miss; 246 Label miss;
245 247
246 __ ldr(r0, MemOperand(sp, 0));
247
248 StubCompiler::GenerateLoadArrayLength(masm, r0, r3, &miss); 248 StubCompiler::GenerateLoadArrayLength(masm, r0, r3, &miss);
249 __ bind(&miss); 249 __ bind(&miss);
250 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 250 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
251 } 251 }
252 252
253 253
254 void LoadIC::GenerateStringLength(MacroAssembler* masm) { 254 void LoadIC::GenerateStringLength(MacroAssembler* masm) {
255 // ----------- S t a t e ------------- 255 // ----------- S t a t e -------------
256 // -- r2 : name 256 // -- r2 : name
257 // -- lr : return address 257 // -- lr : return address
258 // -- [sp] : receiver 258 // -- r0 : receiver
259 // -- sp[0] : receiver
259 // ----------------------------------- 260 // -----------------------------------
260 Label miss; 261 Label miss;
261 262
262 __ ldr(r0, MemOperand(sp, 0));
263
264 StubCompiler::GenerateLoadStringLength(masm, r0, r1, r3, &miss); 263 StubCompiler::GenerateLoadStringLength(masm, r0, r1, r3, &miss);
265 // Cache miss: Jump to runtime. 264 // Cache miss: Jump to runtime.
266 __ bind(&miss); 265 __ bind(&miss);
267 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 266 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
268 } 267 }
269 268
270 269
271 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { 270 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
272 // ----------- S t a t e ------------- 271 // ----------- S t a t e -------------
273 // -- r2 : name 272 // -- r2 : name
274 // -- lr : return address 273 // -- lr : return address
275 // -- [sp] : receiver 274 // -- r0 : receiver
275 // -- sp[0] : receiver
276 // ----------------------------------- 276 // -----------------------------------
277 Label miss; 277 Label miss;
278 278
279 // Load receiver.
280 __ ldr(r0, MemOperand(sp, 0));
281
282 StubCompiler::GenerateLoadFunctionPrototype(masm, r0, r1, r3, &miss); 279 StubCompiler::GenerateLoadFunctionPrototype(masm, r0, r1, r3, &miss);
283 __ bind(&miss); 280 __ bind(&miss);
284 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 281 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
285 } 282 }
286 283
287 284
288 // Defined in ic.cc. 285 // Defined in ic.cc.
289 Object* CallIC_Miss(Arguments args); 286 Object* CallIC_Miss(Arguments args);
290 287
291 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 288 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 341
345 // Cache miss: Jump to runtime. 342 // Cache miss: Jump to runtime.
346 __ bind(&miss); 343 __ bind(&miss);
347 GenerateMiss(masm, argc); 344 GenerateMiss(masm, argc);
348 } 345 }
349 346
350 347
351 static void GenerateNormalHelper(MacroAssembler* masm, 348 static void GenerateNormalHelper(MacroAssembler* masm,
352 int argc, 349 int argc,
353 bool is_global_object, 350 bool is_global_object,
354 Label* miss) { 351 Label* miss,
352 Register scratch) {
355 // Search dictionary - put result in register r1. 353 // Search dictionary - put result in register r1.
356 GenerateDictionaryLoad(masm, miss, r0, r1); 354 GenerateDictionaryLoad(masm, miss, r0, r1);
357 355
358 // Check that the value isn't a smi. 356 // Check that the value isn't a smi.
359 __ tst(r1, Operand(kSmiTagMask)); 357 __ tst(r1, Operand(kSmiTagMask));
360 __ b(eq, miss); 358 __ b(eq, miss);
361 359
362 // Check that the value is a JSFunction. 360 // Check that the value is a JSFunction.
363 __ CompareObjectType(r1, r0, r0, JS_FUNCTION_TYPE); 361 __ CompareObjectType(r1, scratch, scratch, JS_FUNCTION_TYPE);
364 __ b(ne, miss); 362 __ b(ne, miss);
365 363
366 // Patch the receiver with the global proxy if necessary. 364 // Patch the receiver with the global proxy if necessary.
367 if (is_global_object) { 365 if (is_global_object) {
368 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 366 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
369 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 367 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
370 __ str(r0, MemOperand(sp, argc * kPointerSize)); 368 __ str(r0, MemOperand(sp, argc * kPointerSize));
371 } 369 }
372 370
373 // Invoke the function. 371 // Invoke the function.
(...skipping 28 matching lines...) Expand all
402 __ b(eq, &global_object); 400 __ b(eq, &global_object);
403 __ cmp(r0, Operand(JS_BUILTINS_OBJECT_TYPE)); 401 __ cmp(r0, Operand(JS_BUILTINS_OBJECT_TYPE));
404 __ b(ne, &non_global_object); 402 __ b(ne, &non_global_object);
405 403
406 // Accessing global object: Load and invoke. 404 // Accessing global object: Load and invoke.
407 __ bind(&global_object); 405 __ bind(&global_object);
408 // Check that the global object does not require access checks. 406 // Check that the global object does not require access checks.
409 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset)); 407 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
410 __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded)); 408 __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
411 __ b(ne, &miss); 409 __ b(ne, &miss);
412 GenerateNormalHelper(masm, argc, true, &miss); 410 GenerateNormalHelper(masm, argc, true, &miss, r4);
413 411
414 // Accessing non-global object: Check for access to global proxy. 412 // Accessing non-global object: Check for access to global proxy.
415 Label global_proxy, invoke; 413 Label global_proxy, invoke;
416 __ bind(&non_global_object); 414 __ bind(&non_global_object);
417 __ cmp(r0, Operand(JS_GLOBAL_PROXY_TYPE)); 415 __ cmp(r0, Operand(JS_GLOBAL_PROXY_TYPE));
418 __ b(eq, &global_proxy); 416 __ b(eq, &global_proxy);
419 // Check that the non-global, non-global-proxy object does not 417 // Check that the non-global, non-global-proxy object does not
420 // require access checks. 418 // require access checks.
421 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset)); 419 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
422 __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded)); 420 __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
423 __ b(ne, &miss); 421 __ b(ne, &miss);
424 __ bind(&invoke); 422 __ bind(&invoke);
425 GenerateNormalHelper(masm, argc, false, &miss); 423 GenerateNormalHelper(masm, argc, false, &miss, r4);
426 424
427 // Global object access: Check access rights. 425 // Global object access: Check access rights.
428 __ bind(&global_proxy); 426 __ bind(&global_proxy);
429 __ CheckAccessGlobalProxy(r1, r0, &miss); 427 __ CheckAccessGlobalProxy(r1, r0, &miss);
430 __ b(&invoke); 428 __ b(&invoke);
431 429
432 // Cache miss: Jump to runtime. 430 // Cache miss: Jump to runtime.
433 __ bind(&miss); 431 __ bind(&miss);
434 GenerateMiss(masm, argc); 432 GenerateMiss(masm, argc);
435 } 433 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 } 480 }
483 481
484 482
485 // Defined in ic.cc. 483 // Defined in ic.cc.
486 Object* LoadIC_Miss(Arguments args); 484 Object* LoadIC_Miss(Arguments args);
487 485
488 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { 486 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
489 // ----------- S t a t e ------------- 487 // ----------- S t a t e -------------
490 // -- r2 : name 488 // -- r2 : name
491 // -- lr : return address 489 // -- lr : return address
492 // -- [sp] : receiver 490 // -- r0 : receiver
491 // -- sp[0] : receiver
493 // ----------------------------------- 492 // -----------------------------------
494 493
495 __ ldr(r0, MemOperand(sp, 0));
496 // Probe the stub cache. 494 // Probe the stub cache.
497 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, 495 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
498 NOT_IN_LOOP, 496 NOT_IN_LOOP,
499 MONOMORPHIC); 497 MONOMORPHIC);
500 StubCache::GenerateProbe(masm, flags, r0, r2, r3, no_reg); 498 StubCache::GenerateProbe(masm, flags, r0, r2, r3, no_reg);
501 499
502 // Cache miss: Jump to runtime. 500 // Cache miss: Jump to runtime.
503 GenerateMiss(masm); 501 GenerateMiss(masm);
504 } 502 }
505 503
506 504
507 void LoadIC::GenerateNormal(MacroAssembler* masm) { 505 void LoadIC::GenerateNormal(MacroAssembler* masm) {
508 // ----------- S t a t e ------------- 506 // ----------- S t a t e -------------
509 // -- r2 : name 507 // -- r2 : name
510 // -- lr : return address 508 // -- lr : return address
511 // -- [sp] : receiver 509 // -- r0 : receiver
510 // -- sp[0] : receiver
512 // ----------------------------------- 511 // -----------------------------------
513 Label miss, probe, global; 512 Label miss, probe, global;
514 513
515 __ ldr(r0, MemOperand(sp, 0));
516 // Check that the receiver isn't a smi. 514 // Check that the receiver isn't a smi.
517 __ tst(r0, Operand(kSmiTagMask)); 515 __ tst(r0, Operand(kSmiTagMask));
518 __ b(eq, &miss); 516 __ b(eq, &miss);
519 517
520 // Check that the receiver is a valid JS object. Put the map in r3. 518 // Check that the receiver is a valid JS object. Put the map in r3.
521 __ CompareObjectType(r0, r3, r1, FIRST_JS_OBJECT_TYPE); 519 __ CompareObjectType(r0, r3, r1, FIRST_JS_OBJECT_TYPE);
522 __ b(lt, &miss); 520 __ b(lt, &miss);
523 // If this assert fails, we have to check upper bound too. 521 // If this assert fails, we have to check upper bound too.
524 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 522 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
525 523
(...skipping 18 matching lines...) Expand all
544 // Cache miss: Restore receiver from stack and jump to runtime. 542 // Cache miss: Restore receiver from stack and jump to runtime.
545 __ bind(&miss); 543 __ bind(&miss);
546 GenerateMiss(masm); 544 GenerateMiss(masm);
547 } 545 }
548 546
549 547
550 void LoadIC::GenerateMiss(MacroAssembler* masm) { 548 void LoadIC::GenerateMiss(MacroAssembler* masm) {
551 // ----------- S t a t e ------------- 549 // ----------- S t a t e -------------
552 // -- r2 : name 550 // -- r2 : name
553 // -- lr : return address 551 // -- lr : return address
554 // -- [sp] : receiver 552 // -- r0 : receiver
553 // -- sp[0] : receiver
555 // ----------------------------------- 554 // -----------------------------------
556 555
557 __ ldr(r3, MemOperand(sp, 0)); 556 __ mov(r3, r0);
558 __ stm(db_w, sp, r2.bit() | r3.bit()); 557 __ Push(r3, r2);
559 558
560 // Perform tail call to the entry. 559 // Perform tail call to the entry.
561 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); 560 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss));
562 __ TailCallExternalReference(ref, 2, 1); 561 __ TailCallExternalReference(ref, 2, 1);
563 } 562 }
564 563
565 564
566 void LoadIC::ClearInlinedVersion(Address address) { 565 void LoadIC::ClearInlinedVersion(Address address) {
567 // Reset the map check of the inlined inobject property load (if present) to 566 // Reset the map check of the inlined inobject property load (if present) to
568 // guarantee failure by holding an invalid map (the null value). The offset 567 // guarantee failure by holding an invalid map (the null value). The offset
(...skipping 1166 matching lines...) Expand 10 before | Expand all | Expand 10 after
1735 __ bind(&miss); 1734 __ bind(&miss);
1736 1735
1737 GenerateMiss(masm); 1736 GenerateMiss(masm);
1738 } 1737 }
1739 1738
1740 1739
1741 #undef __ 1740 #undef __
1742 1741
1743 1742
1744 } } // namespace v8::internal 1743 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698