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

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

Issue 2853003: Port KeyedCallIC implementation to x64 and ARM.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 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
« no previous file with comments | « src/arm/full-codegen-arm.cc ('k') | src/arm/stub-cache-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 // Get the value at the masked, scaled index and return. 160 // Get the value at the masked, scaled index and return.
161 __ ldr(result, 161 __ ldr(result,
162 FieldMemOperand(scratch3, kElementsStartOffset + 1 * kPointerSize)); 162 FieldMemOperand(scratch3, kElementsStartOffset + 1 * kPointerSize));
163 } 163 }
164 164
165 165
166 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, 166 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
167 Label* miss, 167 Label* miss,
168 Register elements, 168 Register elements,
169 Register key, 169 Register key,
170 Register result,
170 Register t0, 171 Register t0,
171 Register t1, 172 Register t1,
172 Register t2) { 173 Register t2) {
173 // Register use: 174 // Register use:
174 // 175 //
175 // elements - holds the slow-case elements of the receiver and is unchanged. 176 // elements - holds the slow-case elements of the receiver on entry.
177 // Unchanged unless 'result' is the same register.
176 // 178 //
177 // key - holds the smi key on entry and is unchanged if a branch is 179 // key - holds the smi key on entry.
178 // performed to the miss label. 180 // Unchanged unless 'result' is the same register.
179 // Holds the result on exit if the load succeeded. 181 //
182 // result - holds the result on exit if the load succeeded.
183 // Allowed to be the same as 'key' or 'result'.
184 // Unchanged on bailout so 'key' or 'result' can be used
185 // in further computation.
180 // 186 //
181 // Scratch registers: 187 // Scratch registers:
182 // 188 //
183 // t0 - holds the untagged key on entry and holds the hash once computed. 189 // t0 - holds the untagged key on entry and holds the hash once computed.
184 // 190 //
185 // t1 - used to hold the capacity mask of the dictionary 191 // t1 - used to hold the capacity mask of the dictionary
186 // 192 //
187 // t2 - used for the index into the dictionary. 193 // t2 - used for the index into the dictionary.
188 Label done; 194 Label done;
189 195
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 // t2: elements + (index * kPointerSize) 247 // t2: elements + (index * kPointerSize)
242 const int kDetailsOffset = 248 const int kDetailsOffset =
243 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; 249 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
244 __ ldr(t1, FieldMemOperand(t2, kDetailsOffset)); 250 __ ldr(t1, FieldMemOperand(t2, kDetailsOffset));
245 __ tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::mask()))); 251 __ tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::mask())));
246 __ b(ne, miss); 252 __ b(ne, miss);
247 253
248 // Get the value at the masked, scaled index and return. 254 // Get the value at the masked, scaled index and return.
249 const int kValueOffset = 255 const int kValueOffset =
250 NumberDictionary::kElementsStartOffset + kPointerSize; 256 NumberDictionary::kElementsStartOffset + kPointerSize;
251 __ ldr(key, FieldMemOperand(t2, kValueOffset)); 257 __ ldr(result, FieldMemOperand(t2, kValueOffset));
252 } 258 }
253 259
254 260
255 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { 261 void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
256 // ----------- S t a t e ------------- 262 // ----------- S t a t e -------------
257 // -- r2 : name 263 // -- r2 : name
258 // -- lr : return address 264 // -- lr : return address
259 // -- r0 : receiver 265 // -- r0 : receiver
260 // -- sp[0] : receiver 266 // -- sp[0] : receiver
261 // ----------------------------------- 267 // -----------------------------------
(...skipping 29 matching lines...) Expand all
291 // -- sp[0] : receiver 297 // -- sp[0] : receiver
292 // ----------------------------------- 298 // -----------------------------------
293 Label miss; 299 Label miss;
294 300
295 StubCompiler::GenerateLoadFunctionPrototype(masm, r0, r1, r3, &miss); 301 StubCompiler::GenerateLoadFunctionPrototype(masm, r0, r1, r3, &miss);
296 __ bind(&miss); 302 __ bind(&miss);
297 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 303 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
298 } 304 }
299 305
300 306
307 // Checks the receiver for special cases (value type, slow case bits).
308 // Falls through for regular JS object.
309 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
310 Register receiver,
311 Register scratch1,
312 Register scratch2,
313 Label* slow) {
314 // Check that the object isn't a smi.
315 __ BranchOnSmi(receiver, slow);
316 // Get the map of the receiver.
317 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
318 // Check bit field.
319 __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
320 __ tst(scratch2, Operand(KeyedLoadIC::kSlowCaseBitFieldMask));
321 __ b(ne, slow);
322 // Check that the object is some kind of JS object EXCEPT JS Value type.
323 // In the case that the object is a value-wrapper object,
324 // we enter the runtime system to make sure that indexing into string
325 // objects work as intended.
326 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
327 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
328 __ cmp(scratch1, Operand(JS_OBJECT_TYPE));
329 __ b(lt, slow);
330 }
331
332
333 // Loads an indexed element from a fast case array.
334 static void GenerateFastArrayLoad(MacroAssembler* masm,
335 Register receiver,
336 Register key,
337 Register elements,
338 Register scratch1,
339 Register scratch2,
340 Register result,
341 Label* not_fast_array,
342 Label* out_of_range) {
343 // Register use:
344 //
345 // receiver - holds the receiver on entry.
346 // Unchanged unless 'result' is the same register.
347 //
348 // key - holds the smi key on entry.
349 // Unchanged unless 'result' is the same register.
350 //
351 // elements - holds the elements of the receiver on exit.
352 //
353 // result - holds the result on exit if the load succeeded.
354 // Allowed to be the the same as 'receiver' or 'key'.
355 // Unchanged on bailout so 'receiver' and 'key' can be safely
356 // used by further computation.
357 //
358 // Scratch registers:
359 //
360 // scratch1 - used to hold elements map and elements length.
361 // Holds the elements map if not_fast_array branch is taken.
362 //
363 // scratch2 - used to hold the loaded value.
364
365 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
366 // Check that the object is in fast mode (not dictionary).
367 __ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset));
368 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
369 __ cmp(scratch1, ip);
370 __ b(ne, not_fast_array);
371 // Check that the key (index) is within bounds.
372 __ ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset));
373 __ cmp(key, Operand(scratch1));
374 __ b(hs, out_of_range);
375 // Fast case: Do the load.
376 __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
377 // The key is a smi.
378 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
379 __ ldr(scratch2,
380 MemOperand(scratch1, key, LSL, kPointerSizeLog2 - kSmiTagSize));
381 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
382 __ cmp(scratch2, ip);
383 // In case the loaded value is the_hole we have to consult GetProperty
384 // to ensure the prototype chain is searched.
385 __ b(eq, out_of_range);
386 __ mov(result, scratch2);
387 }
388
389
390 // Checks whether a key is an array index string or a symbol string.
391 // Falls through if a key is a symbol.
392 static void GenerateKeyStringCheck(MacroAssembler* masm,
393 Register key,
394 Register map,
395 Register hash,
396 Label* index_string,
397 Label* not_symbol) {
398 // The key is not a smi.
399 // Is it a string?
400 __ CompareObjectType(key, map, hash, FIRST_NONSTRING_TYPE);
401 __ b(ge, not_symbol);
402
403 // Is the string an array index, with cached numeric value?
404 __ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset));
405 __ tst(hash, Operand(String::kContainsCachedArrayIndexMask));
406 __ b(eq, index_string);
407
408 // Is the string a symbol?
409 // map: key map
410 __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset));
411 ASSERT(kSymbolTag != 0);
412 __ tst(hash, Operand(kIsSymbolMask));
413 __ b(eq, not_symbol);
414 }
415
416
417 // Picks out an array index from the hash field.
418 static void GenerateIndexFromHash(MacroAssembler* masm,
419 Register key,
420 Register hash) {
421 // Register use:
422 // key - holds the overwritten key on exit.
423 // hash - holds the key's hash. Clobbered.
424
425 // If the hash field contains an array index pick it out. The assert checks
426 // that the constants for the maximum number of digits for an array index
427 // cached in the hash field and the number of bits reserved for it does not
428 // conflict.
429 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
430 (1 << String::kArrayIndexValueBits));
431 // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in
432 // the low kHashShift bits.
433 ASSERT(String::kHashShift >= kSmiTagSize);
434 // Here we actually clobber the key which will be used if calling into
435 // runtime later. However as the new key is the numeric value of a string key
436 // there is no difference in using either key.
437 ASSERT(String::kHashShift >= kSmiTagSize);
438 __ Ubfx(hash, hash, String::kHashShift, String::kArrayIndexValueBits);
439 __ mov(key, Operand(hash, LSL, kSmiTagSize));
440 }
441
442
301 // Defined in ic.cc. 443 // Defined in ic.cc.
302 Object* CallIC_Miss(Arguments args); 444 Object* CallIC_Miss(Arguments args);
303 445
304 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 446 // The generated code does not accept smi keys.
447 // The generated code falls through if both probes miss.
448 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
449 int argc,
450 Code::Kind kind) {
305 // ----------- S t a t e ------------- 451 // ----------- S t a t e -------------
452 // -- r1 : receiver
306 // -- r2 : name 453 // -- r2 : name
307 // -- lr : return address
308 // ----------------------------------- 454 // -----------------------------------
309 Label number, non_number, non_string, boolean, probe, miss; 455 Label number, non_number, non_string, boolean, probe, miss;
310 456
311 // Get the receiver of the function from the stack into r1.
312 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
313
314 // Probe the stub cache. 457 // Probe the stub cache.
315 Code::Flags flags = 458 Code::Flags flags =
316 Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); 459 Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
317 StubCache::GenerateProbe(masm, flags, r1, r2, r3, no_reg); 460 StubCache::GenerateProbe(masm, flags, r1, r2, r3, no_reg);
318 461
319 // If the stub cache probing failed, the receiver might be a value. 462 // If the stub cache probing failed, the receiver might be a value.
320 // For value objects, we use the map of the prototype objects for 463 // For value objects, we use the map of the prototype objects for
321 // the corresponding JSValue for the cache and that is what we need 464 // the corresponding JSValue for the cache and that is what we need
322 // to probe. 465 // to probe.
323 // 466 //
324 // Check for number. 467 // Check for number.
325 __ tst(r1, Operand(kSmiTagMask)); 468 __ tst(r1, Operand(kSmiTagMask));
326 __ b(eq, &number); 469 __ b(eq, &number);
(...skipping 21 matching lines...) Expand all
348 __ cmp(r1, ip); 491 __ cmp(r1, ip);
349 __ b(ne, &miss); 492 __ b(ne, &miss);
350 __ bind(&boolean); 493 __ bind(&boolean);
351 StubCompiler::GenerateLoadGlobalFunctionPrototype( 494 StubCompiler::GenerateLoadGlobalFunctionPrototype(
352 masm, Context::BOOLEAN_FUNCTION_INDEX, r1); 495 masm, Context::BOOLEAN_FUNCTION_INDEX, r1);
353 496
354 // Probe the stub cache for the value object. 497 // Probe the stub cache for the value object.
355 __ bind(&probe); 498 __ bind(&probe);
356 StubCache::GenerateProbe(masm, flags, r1, r2, r3, no_reg); 499 StubCache::GenerateProbe(masm, flags, r1, r2, r3, no_reg);
357 500
358 // Cache miss: Jump to runtime.
359 __ bind(&miss); 501 __ bind(&miss);
360 GenerateMiss(masm, argc);
361 } 502 }
362 503
363 504
364 static void GenerateNormalHelper(MacroAssembler* masm, 505 static void GenerateNormalHelper(MacroAssembler* masm,
365 int argc, 506 int argc,
366 bool is_global_object, 507 bool is_global_object,
367 Label* miss, 508 Label* miss,
368 Register scratch) { 509 Register scratch) {
369 // Search dictionary - put result in register r1. 510 // Search dictionary - put result in register r1.
370 GenerateDictionaryLoad(masm, miss, r1, r2, r1, r0, r3, r4, CHECK_DICTIONARY); 511 GenerateDictionaryLoad(masm, miss, r1, r2, r1, r0, r3, r4, CHECK_DICTIONARY);
(...skipping 12 matching lines...) Expand all
383 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 524 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
384 __ str(r0, MemOperand(sp, argc * kPointerSize)); 525 __ str(r0, MemOperand(sp, argc * kPointerSize));
385 } 526 }
386 527
387 // Invoke the function. 528 // Invoke the function.
388 ParameterCount actual(argc); 529 ParameterCount actual(argc);
389 __ InvokeFunction(r1, actual, JUMP_FUNCTION); 530 __ InvokeFunction(r1, actual, JUMP_FUNCTION);
390 } 531 }
391 532
392 533
393 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { 534 static void GenerateCallNormal(MacroAssembler* masm, int argc) {
394 // ----------- S t a t e ------------- 535 // ----------- S t a t e -------------
395 // -- r2 : name 536 // -- r2 : name
396 // -- lr : return address 537 // -- lr : return address
397 // ----------------------------------- 538 // -----------------------------------
398 Label miss, global_object, non_global_object; 539 Label miss, global_object, non_global_object;
399 540
400 // Get the receiver of the function from the stack into r1. 541 // Get the receiver of the function from the stack into r1.
401 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 542 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
402 543
403 // Check that the receiver isn't a smi. 544 // Check that the receiver isn't a smi.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded)); 577 __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
437 __ b(ne, &miss); 578 __ b(ne, &miss);
438 __ bind(&invoke); 579 __ bind(&invoke);
439 GenerateNormalHelper(masm, argc, false, &miss, r4); 580 GenerateNormalHelper(masm, argc, false, &miss, r4);
440 581
441 // Global object access: Check access rights. 582 // Global object access: Check access rights.
442 __ bind(&global_proxy); 583 __ bind(&global_proxy);
443 __ CheckAccessGlobalProxy(r1, r0, &miss); 584 __ CheckAccessGlobalProxy(r1, r0, &miss);
444 __ b(&invoke); 585 __ b(&invoke);
445 586
446 // Cache miss: Jump to runtime.
447 __ bind(&miss); 587 __ bind(&miss);
448 GenerateMiss(masm, argc);
449 } 588 }
450 589
451 590
452 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { 591 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) {
453 // ----------- S t a t e ------------- 592 // ----------- S t a t e -------------
454 // -- r2 : name 593 // -- r2 : name
455 // -- lr : return address 594 // -- lr : return address
456 // ----------------------------------- 595 // -----------------------------------
457 596
458 // Get the receiver of the function from the stack. 597 // Get the receiver of the function from the stack.
459 __ ldr(r3, MemOperand(sp, argc * kPointerSize)); 598 __ ldr(r3, MemOperand(sp, argc * kPointerSize));
460 599
461 __ EnterInternalFrame(); 600 __ EnterInternalFrame();
462 601
463 // Push the receiver and the name of the function. 602 // Push the receiver and the name of the function.
464 __ Push(r3, r2); 603 __ Push(r3, r2);
465 604
466 // Call the entry. 605 // Call the entry.
467 __ mov(r0, Operand(2)); 606 __ mov(r0, Operand(2));
468 __ mov(r1, Operand(ExternalReference(IC_Utility(kCallIC_Miss)))); 607 __ mov(r1, Operand(ExternalReference(IC_Utility(id))));
469 608
470 CEntryStub stub(1); 609 CEntryStub stub(1);
471 __ CallStub(&stub); 610 __ CallStub(&stub);
472 611
473 // Move result to r1 and leave the internal frame. 612 // Move result to r1 and leave the internal frame.
474 __ mov(r1, Operand(r0)); 613 __ mov(r1, Operand(r0));
475 __ LeaveInternalFrame(); 614 __ LeaveInternalFrame();
476 615
477 // Check if the receiver is a global object of some sort. 616 // Check if the receiver is a global object of some sort.
478 Label invoke, global; 617 Label invoke, global;
(...skipping 10 matching lines...) Expand all
489 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); 628 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
490 __ str(r2, MemOperand(sp, argc * kPointerSize)); 629 __ str(r2, MemOperand(sp, argc * kPointerSize));
491 630
492 // Invoke the function. 631 // Invoke the function.
493 ParameterCount actual(argc); 632 ParameterCount actual(argc);
494 __ bind(&invoke); 633 __ bind(&invoke);
495 __ InvokeFunction(r1, actual, JUMP_FUNCTION); 634 __ InvokeFunction(r1, actual, JUMP_FUNCTION);
496 } 635 }
497 636
498 637
638 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
639 // ----------- S t a t e -------------
640 // -- r2 : name
641 // -- lr : return address
642 // -----------------------------------
643
644 GenerateCallMiss(masm, argc, IC::kCallIC_Miss);
645 }
646
647
648 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
649 // ----------- S t a t e -------------
650 // -- r2 : name
651 // -- lr : return address
652 // -----------------------------------
653
654 // Get the receiver of the function from the stack into r1.
655 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
656 GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC);
657 GenerateMiss(masm, argc);
658 }
659
660
661 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
662 // ----------- S t a t e -------------
663 // -- r2 : name
664 // -- lr : return address
665 // -----------------------------------
666
667 GenerateCallNormal(masm, argc);
668 GenerateMiss(masm, argc);
669 }
670
671
499 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { 672 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
500 UNREACHABLE(); 673 // ----------- S t a t e -------------
674 // -- r2 : name
675 // -- lr : return address
676 // -----------------------------------
677
678 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss);
501 } 679 }
502 680
503 681
504 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 682 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
505 UNREACHABLE(); 683 // ----------- S t a t e -------------
684 // -- r2 : name
685 // -- lr : return address
686 // -----------------------------------
687
688 // Get the receiver of the function from the stack into r1.
689 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
690
691 Label do_call, slow_call, slow_load, slow_reload_receiver;
692 Label check_number_dictionary, check_string, lookup_monomorphic_cache;
693 Label index_smi, index_string;
694
695 // Check that the key is a smi.
696 __ BranchOnNotSmi(r2, &check_string);
697 __ bind(&index_smi);
698 // Now the key is known to be a smi. This place is also jumped to from below
699 // where a numeric string is converted to a smi.
700
701 GenerateKeyedLoadReceiverCheck(masm, r1, r0, r3, &slow_call);
702
703 GenerateFastArrayLoad(
704 masm, r1, r2, r4, r3, r0, r1, &check_number_dictionary, &slow_load);
705 __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1, r0, r3);
706
707 __ bind(&do_call);
708 // receiver in r1 is not used after this point.
709 // r2: key
710 // r1: function
711
712 // Check that the value in r1 is a JSFunction.
713 __ BranchOnSmi(r1, &slow_call);
714 __ CompareObjectType(r1, r0, r0, JS_FUNCTION_TYPE);
715 __ b(ne, &slow_call);
716 // Invoke the function.
717 ParameterCount actual(argc);
718 __ InvokeFunction(r1, actual, JUMP_FUNCTION);
719
720 __ bind(&check_number_dictionary);
721 // r2: key
722 // r3: elements map
723 // r4: elements
724 // Check whether the elements is a number dictionary.
725 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
726 __ cmp(r3, ip);
727 __ b(ne, &slow_load);
728 __ mov(r0, Operand(r2, ASR, kSmiTagSize));
729 // r0: untagged index
730 GenerateNumberDictionaryLoad(masm, &slow_load, r4, r2, r1, r0, r3, r5);
731 __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1, r0, r3);
732 __ jmp(&do_call);
733
734 __ bind(&slow_load);
735 // This branch is taken when calling KeyedCallIC_Miss is neither required
736 // nor beneficial.
737 __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1, r0, r3);
738 __ EnterInternalFrame();
739 __ push(r2); // save the key
740 __ Push(r1, r2); // pass the receiver and the key
741 __ CallRuntime(Runtime::kKeyedGetProperty, 2);
742 __ pop(r2); // restore the key
743 __ LeaveInternalFrame();
744 __ mov(r1, r0);
745 __ jmp(&do_call);
746
747 __ bind(&check_string);
748 GenerateKeyStringCheck(masm, r2, r0, r3, &index_string, &slow_call);
749
750 // The key is known to be a symbol.
751 // If the receiver is a regular JS object with slow properties then do
752 // a quick inline probe of the receiver's dictionary.
753 // Otherwise do the monomorphic cache probe.
754 GenerateKeyedLoadReceiverCheck(masm, r1, r0, r3, &lookup_monomorphic_cache);
755
756 __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset));
757 __ ldr(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
758 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
759 __ cmp(r3, ip);
760 __ b(ne, &lookup_monomorphic_cache);
761
762 GenerateDictionaryLoad(
763 masm, &slow_load, r1, r2, r1, r0, r3, r4, DICTIONARY_CHECK_DONE);
764 __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1, r0, r3);
765 __ jmp(&do_call);
766
767 __ bind(&lookup_monomorphic_cache);
768 __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1, r0, r3);
769 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC);
770 // Fall through on miss.
771
772 __ bind(&slow_call);
773 // This branch is taken if:
774 // - the receiver requires boxing or access check,
775 // - the key is neither smi nor symbol,
776 // - the value loaded is not a function,
777 // - there is hope that the runtime will create a monomorphic call stub
778 // that will get fetched next time.
779 __ IncrementCounter(&Counters::keyed_call_generic_slow, 1, r0, r3);
780 GenerateMiss(masm, argc);
781
782 __ bind(&index_string);
783 GenerateIndexFromHash(masm, r2, r3);
784 // Now jump to the place where smi keys are handled.
785 __ jmp(&index_smi);
506 } 786 }
507 787
508 788
509 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { 789 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
510 UNREACHABLE(); 790 // ----------- S t a t e -------------
791 // -- r2 : name
792 // -- lr : return address
793 // -----------------------------------
794
795 GenerateCallNormal(masm, argc);
796 GenerateMiss(masm, argc);
511 } 797 }
512 798
513 799
514 // Defined in ic.cc. 800 // Defined in ic.cc.
515 Object* LoadIC_Miss(Arguments args); 801 Object* LoadIC_Miss(Arguments args);
516 802
517 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { 803 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
518 // ----------- S t a t e ------------- 804 // ----------- S t a t e -------------
519 // -- r2 : name 805 // -- r2 : name
520 // -- lr : return address 806 // -- lr : return address
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 // -- lr : return address 1038 // -- lr : return address
753 // -- r0 : key 1039 // -- r0 : key
754 // -- r1 : receiver 1040 // -- r1 : receiver
755 // ----------------------------------- 1041 // -----------------------------------
756 Label slow, check_string, index_smi, index_string; 1042 Label slow, check_string, index_smi, index_string;
757 Label check_pixel_array, probe_dictionary, check_number_dictionary; 1043 Label check_pixel_array, probe_dictionary, check_number_dictionary;
758 1044
759 Register key = r0; 1045 Register key = r0;
760 Register receiver = r1; 1046 Register receiver = r1;
761 1047
762 // Check that the object isn't a smi. 1048 GenerateKeyedLoadReceiverCheck(masm, receiver, r2, r3, &slow);
763 __ BranchOnSmi(receiver, &slow);
764 // Get the map of the receiver.
765 __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset));
766 // Check bit field.
767 __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
768 __ tst(r3, Operand(kSlowCaseBitFieldMask));
769 __ b(ne, &slow);
770 // Check that the object is some kind of JS object EXCEPT JS Value type.
771 // In the case that the object is a value-wrapper object,
772 // we enter the runtime system to make sure that indexing into string
773 // objects work as intended.
774 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
775 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
776 __ cmp(r2, Operand(JS_OBJECT_TYPE));
777 __ b(lt, &slow);
778 1049
779 // Check that the key is a smi. 1050 // Check that the key is a smi.
780 __ BranchOnNotSmi(key, &check_string); 1051 __ BranchOnNotSmi(key, &check_string);
781 __ bind(&index_smi); 1052 __ bind(&index_smi);
782 // Now the key is known to be a smi. This place is also jumped to from below 1053 // Now the key is known to be a smi. This place is also jumped to from below
783 // where a numeric string is converted to a smi. 1054 // where a numeric string is converted to a smi.
784 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); 1055
785 // Check that the object is in fast mode (not dictionary). 1056 GenerateFastArrayLoad(
786 __ ldr(r3, FieldMemOperand(r4, HeapObject::kMapOffset)); 1057 masm, receiver, key, r4, r3, r2, r0, &check_pixel_array, &slow);
787 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
788 __ cmp(r3, ip);
789 __ b(ne, &check_pixel_array);
790 // Check that the key (index) is within bounds.
791 __ ldr(r3, FieldMemOperand(r4, FixedArray::kLengthOffset));
792 __ cmp(key, Operand(r3));
793 __ b(hs, &slow);
794 // Fast case: Do the load.
795 __ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
796 // The key is a smi.
797 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
798 __ ldr(r2, MemOperand(r3, key, LSL, kPointerSizeLog2 - kSmiTagSize));
799 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
800 __ cmp(r2, ip);
801 // In case the loaded value is the_hole we have to consult GetProperty
802 // to ensure the prototype chain is searched.
803 __ b(eq, &slow);
804 __ mov(r0, r2);
805 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1, r2, r3); 1058 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1, r2, r3);
806 __ Ret(); 1059 __ Ret();
807 1060
808 // Check whether the elements is a pixel array. 1061 // Check whether the elements is a pixel array.
809 // r0: key 1062 // r0: key
810 // r3: elements map 1063 // r3: elements map
811 // r4: elements 1064 // r4: elements
812 __ bind(&check_pixel_array); 1065 __ bind(&check_pixel_array);
813 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex); 1066 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
814 __ cmp(r3, ip); 1067 __ cmp(r3, ip);
815 __ b(ne, &check_number_dictionary); 1068 __ b(ne, &check_number_dictionary);
816 __ ldr(ip, FieldMemOperand(r4, PixelArray::kLengthOffset)); 1069 __ ldr(ip, FieldMemOperand(r4, PixelArray::kLengthOffset));
817 __ mov(r2, Operand(key, ASR, kSmiTagSize)); 1070 __ mov(r2, Operand(key, ASR, kSmiTagSize));
818 __ cmp(r2, ip); 1071 __ cmp(r2, ip);
819 __ b(hs, &slow); 1072 __ b(hs, &slow);
820 __ ldr(ip, FieldMemOperand(r4, PixelArray::kExternalPointerOffset)); 1073 __ ldr(ip, FieldMemOperand(r4, PixelArray::kExternalPointerOffset));
821 __ ldrb(r2, MemOperand(ip, r2)); 1074 __ ldrb(r2, MemOperand(ip, r2));
822 __ mov(r0, Operand(r2, LSL, kSmiTagSize)); // Tag result as smi. 1075 __ mov(r0, Operand(r2, LSL, kSmiTagSize)); // Tag result as smi.
823 __ Ret(); 1076 __ Ret();
824 1077
825 __ bind(&check_number_dictionary); 1078 __ bind(&check_number_dictionary);
826 // Check whether the elements is a number dictionary. 1079 // Check whether the elements is a number dictionary.
827 // r0: key 1080 // r0: key
828 // r3: elements map 1081 // r3: elements map
829 // r4: elements 1082 // r4: elements
830 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 1083 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
831 __ cmp(r3, ip); 1084 __ cmp(r3, ip);
832 __ b(ne, &slow); 1085 __ b(ne, &slow);
833 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); 1086 __ mov(r2, Operand(r0, ASR, kSmiTagSize));
834 GenerateNumberDictionaryLoad(masm, &slow, r4, r0, r2, r3, r5); 1087 GenerateNumberDictionaryLoad(masm, &slow, r4, r0, r0, r2, r3, r5);
835 __ Ret(); 1088 __ Ret();
836 1089
837 // Slow case, key and receiver still in r0 and r1. 1090 // Slow case, key and receiver still in r0 and r1.
838 __ bind(&slow); 1091 __ bind(&slow);
839 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r2, r3); 1092 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r2, r3);
840 GenerateRuntimeGetProperty(masm); 1093 GenerateRuntimeGetProperty(masm);
841 1094
842 __ bind(&check_string); 1095 __ bind(&check_string);
843 // The key is not a smi. 1096 GenerateKeyStringCheck(masm, key, r2, r3, &index_string, &slow);
844 // Is it a string?
845 // r0: key
846 // r1: receiver
847 __ CompareObjectType(r0, r2, r3, FIRST_NONSTRING_TYPE);
848 __ b(ge, &slow);
849
850 // Is the string an array index, with cached numeric value?
851 __ ldr(r3, FieldMemOperand(r0, String::kHashFieldOffset));
852 __ tst(r3, Operand(String::kContainsCachedArrayIndexMask));
853 __ b(eq, &index_string);
854
855 // Is the string a symbol?
856 // r2: key map
857 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset));
858 ASSERT(kSymbolTag != 0);
859 __ tst(r3, Operand(kIsSymbolMask));
860 __ b(eq, &slow);
861 1097
862 // If the receiver is a fast-case object, check the keyed lookup 1098 // If the receiver is a fast-case object, check the keyed lookup
863 // cache. Otherwise probe the dictionary. 1099 // cache. Otherwise probe the dictionary.
864 __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset)); 1100 __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset));
865 __ ldr(r3, FieldMemOperand(r3, HeapObject::kMapOffset)); 1101 __ ldr(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
866 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 1102 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
867 __ cmp(r3, ip); 1103 __ cmp(r3, ip);
868 __ b(eq, &probe_dictionary); 1104 __ b(eq, &probe_dictionary);
869 1105
870 // Load the map of the receiver, compute the keyed lookup cache hash 1106 // Load the map of the receiver, compute the keyed lookup cache hash
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 1147
912 // Do a quick inline probe of the receiver's dictionary, if it 1148 // Do a quick inline probe of the receiver's dictionary, if it
913 // exists. 1149 // exists.
914 __ bind(&probe_dictionary); 1150 __ bind(&probe_dictionary);
915 // Load the property to r0. 1151 // Load the property to r0.
916 GenerateDictionaryLoad( 1152 GenerateDictionaryLoad(
917 masm, &slow, r1, r0, r0, r2, r3, r4, DICTIONARY_CHECK_DONE); 1153 masm, &slow, r1, r0, r0, r2, r3, r4, DICTIONARY_CHECK_DONE);
918 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1, r2, r3); 1154 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1, r2, r3);
919 __ Ret(); 1155 __ Ret();
920 1156
921 __ b(&slow);
922 // If the hash field contains an array index pick it out. The assert checks
923 // that the constants for the maximum number of digits for an array index
924 // cached in the hash field and the number of bits reserved for it does not
925 // conflict.
926 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
927 (1 << String::kArrayIndexValueBits));
928 __ bind(&index_string); 1157 __ bind(&index_string);
929 // r0: key (string) 1158 GenerateIndexFromHash(masm, key, r3);
930 // r1: receiver
931 // r3: hash field
932 // We want the smi-tagged index in r0. kArrayIndexValueMask has zeros in
933 // the low kHashShift bits.
934 ASSERT(String::kHashShift >= kSmiTagSize);
935 __ Ubfx(r3, r3, String::kHashShift, String::kArrayIndexValueBits);
936 // Here we actually clobber the key (r0) which will be used if calling into
937 // runtime later. However as the new key is the numeric value of a string key
938 // there is no difference in using either key.
939 __ mov(r0, Operand(r3, LSL, kSmiTagSize));
940 // Now jump to the place where smi keys are handled. 1159 // Now jump to the place where smi keys are handled.
941 __ jmp(&index_smi); 1160 __ jmp(&index_smi);
942 } 1161 }
943 1162
944 1163
945 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 1164 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
946 // ---------- S t a t e -------------- 1165 // ---------- S t a t e --------------
947 // -- lr : return address 1166 // -- lr : return address
948 // -- r0 : key (index) 1167 // -- r0 : key (index)
949 // -- r1 : receiver 1168 // -- r1 : receiver
(...skipping 985 matching lines...) Expand 10 before | Expand all | Expand 10 after
1935 GenerateMiss(masm); 2154 GenerateMiss(masm);
1936 } 2155 }
1937 2156
1938 2157
1939 #undef __ 2158 #undef __
1940 2159
1941 2160
1942 } } // namespace v8::internal 2161 } } // namespace v8::internal
1943 2162
1944 #endif // V8_TARGET_ARCH_ARM 2163 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/full-codegen-arm.cc ('k') | src/arm/stub-cache-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698