OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 // Get the global function with the given index. | 300 // Get the global function with the given index. |
301 Handle<JSFunction> function( | 301 Handle<JSFunction> function( |
302 JSFunction::cast(isolate->native_context()->get(index))); | 302 JSFunction::cast(isolate->native_context()->get(index))); |
303 // Load its initial map. The global functions all have initial maps. | 303 // Load its initial map. The global functions all have initial maps. |
304 __ li(prototype, Handle<Map>(function->initial_map())); | 304 __ li(prototype, Handle<Map>(function->initial_map())); |
305 // Load the prototype from the initial map. | 305 // Load the prototype from the initial map. |
306 __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 306 __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
307 } | 307 } |
308 | 308 |
309 | 309 |
310 // Load a fast property out of a holder object (src). In-object properties | |
311 // are loaded directly otherwise the property is loaded from the properties | |
312 // fixed array. | |
313 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | |
314 Register dst, | |
315 Register src, | |
316 Handle<JSObject> holder, | |
317 PropertyIndex index) { | |
318 DoGenerateFastPropertyLoad( | |
319 masm, dst, src, index.is_inobject(holder), index.translate(holder)); | |
320 } | |
321 | |
322 | |
323 void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm, | 310 void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm, |
324 Register dst, | 311 Register dst, |
325 Register src, | 312 Register src, |
326 bool inobject, | 313 bool inobject, |
327 int index) { | 314 int index) { |
328 int offset = index * kPointerSize; | 315 int offset = index * kPointerSize; |
329 if (!inobject) { | 316 if (!inobject) { |
330 // Calculate the offset into the properties array. | 317 // Calculate the offset into the properties array. |
331 offset = offset + FixedArray::kHeaderSize; | 318 offset = offset + FixedArray::kHeaderSize; |
332 __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); | 319 __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 // Generate StoreField code, value is passed in a0 register. | 413 // Generate StoreField code, value is passed in a0 register. |
427 // After executing generated code, the receiver_reg and name_reg | 414 // After executing generated code, the receiver_reg and name_reg |
428 // may be clobbered. | 415 // may be clobbered. |
429 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 416 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
430 Handle<JSObject> object, | 417 Handle<JSObject> object, |
431 int index, | 418 int index, |
432 Handle<Map> transition, | 419 Handle<Map> transition, |
433 Handle<Name> name, | 420 Handle<Name> name, |
434 Register receiver_reg, | 421 Register receiver_reg, |
435 Register name_reg, | 422 Register name_reg, |
| 423 Register value_reg, |
436 Register scratch1, | 424 Register scratch1, |
437 Register scratch2, | 425 Register scratch2, |
438 Label* miss_label) { | 426 Label* miss_label, |
| 427 Label* miss_restore_name) { |
439 // a0 : value. | 428 // a0 : value. |
440 Label exit; | 429 Label exit; |
441 | 430 |
442 LookupResult lookup(masm->isolate()); | 431 LookupResult lookup(masm->isolate()); |
443 object->Lookup(*name, &lookup); | 432 object->Lookup(*name, &lookup); |
444 if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) { | 433 if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) { |
445 // In sloppy mode, we could just return the value and be done. However, we | 434 // In sloppy mode, we could just return the value and be done. However, we |
446 // might be in strict mode, where we have to throw. Since we cannot tell, | 435 // might be in strict mode, where we have to throw. Since we cannot tell, |
447 // go into slow case unconditionally. | 436 // go into slow case unconditionally. |
448 __ jmp(miss_label); | 437 __ jmp(miss_label); |
(...skipping 16 matching lines...) Expand all Loading... |
465 JSObject* holder; | 454 JSObject* holder; |
466 if (lookup.IsFound()) { | 455 if (lookup.IsFound()) { |
467 holder = lookup.holder(); | 456 holder = lookup.holder(); |
468 } else { | 457 } else { |
469 // Find the top object. | 458 // Find the top object. |
470 holder = *object; | 459 holder = *object; |
471 do { | 460 do { |
472 holder = JSObject::cast(holder->GetPrototype()); | 461 holder = JSObject::cast(holder->GetPrototype()); |
473 } while (holder->GetPrototype()->IsJSObject()); | 462 } while (holder->GetPrototype()->IsJSObject()); |
474 } | 463 } |
475 // We need an extra register, push | |
476 __ push(name_reg); | |
477 Label miss_pop, done_check; | |
478 CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, | 464 CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, |
479 scratch1, scratch2, name, &miss_pop); | 465 scratch1, scratch2, name, miss_restore_name); |
480 __ jmp(&done_check); | |
481 __ bind(&miss_pop); | |
482 __ pop(name_reg); | |
483 __ jmp(miss_label); | |
484 __ bind(&done_check); | |
485 __ pop(name_reg); | |
486 } | 466 } |
487 | 467 |
488 // Stub never generated for non-global objects that require access | 468 // Stub never generated for non-global objects that require access |
489 // checks. | 469 // checks. |
490 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 470 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
491 | 471 |
492 // Perform map transition for the receiver if necessary. | 472 // Perform map transition for the receiver if necessary. |
493 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { | 473 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { |
494 // The properties must be extended before we can store the value. | 474 // The properties must be extended before we can store the value. |
495 // We jump to a runtime call that extends the properties array. | 475 // We jump to a runtime call that extends the properties array. |
(...skipping 25 matching lines...) Expand all Loading... |
521 } | 501 } |
522 | 502 |
523 // Adjust for the number of properties stored in the object. Even in the | 503 // Adjust for the number of properties stored in the object. Even in the |
524 // face of a transition we can use the old map here because the size of the | 504 // face of a transition we can use the old map here because the size of the |
525 // object and the number of in-object properties is not going to change. | 505 // object and the number of in-object properties is not going to change. |
526 index -= object->map()->inobject_properties(); | 506 index -= object->map()->inobject_properties(); |
527 | 507 |
528 if (index < 0) { | 508 if (index < 0) { |
529 // Set the property straight into the object. | 509 // Set the property straight into the object. |
530 int offset = object->map()->instance_size() + (index * kPointerSize); | 510 int offset = object->map()->instance_size() + (index * kPointerSize); |
531 __ sw(a0, FieldMemOperand(receiver_reg, offset)); | 511 __ sw(value_reg, FieldMemOperand(receiver_reg, offset)); |
532 | 512 |
533 // Skip updating write barrier if storing a smi. | 513 // Skip updating write barrier if storing a smi. |
534 __ JumpIfSmi(a0, &exit, scratch1); | 514 __ JumpIfSmi(value_reg, &exit); |
535 | 515 |
536 // Update the write barrier for the array address. | 516 // Update the write barrier for the array address. |
537 // Pass the now unused name_reg as a scratch register. | 517 // Pass the now unused name_reg as a scratch register. |
538 __ mov(name_reg, a0); | 518 __ mov(name_reg, value_reg); |
539 __ RecordWriteField(receiver_reg, | 519 __ RecordWriteField(receiver_reg, |
540 offset, | 520 offset, |
541 name_reg, | 521 name_reg, |
542 scratch1, | 522 scratch1, |
543 kRAHasNotBeenSaved, | 523 kRAHasNotBeenSaved, |
544 kDontSaveFPRegs); | 524 kDontSaveFPRegs); |
545 } else { | 525 } else { |
546 // Write to the properties array. | 526 // Write to the properties array. |
547 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 527 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
548 // Get the properties array. | 528 // Get the properties array. |
549 __ lw(scratch1, | 529 __ lw(scratch1, |
550 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 530 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
551 __ sw(a0, FieldMemOperand(scratch1, offset)); | 531 __ sw(value_reg, FieldMemOperand(scratch1, offset)); |
552 | 532 |
553 // Skip updating write barrier if storing a smi. | 533 // Skip updating write barrier if storing a smi. |
554 __ JumpIfSmi(a0, &exit); | 534 __ JumpIfSmi(value_reg, &exit); |
555 | 535 |
556 // Update the write barrier for the array address. | 536 // Update the write barrier for the array address. |
557 // Ok to clobber receiver_reg and name_reg, since we return. | 537 // Ok to clobber receiver_reg and name_reg, since we return. |
558 __ mov(name_reg, a0); | 538 __ mov(name_reg, value_reg); |
559 __ RecordWriteField(scratch1, | 539 __ RecordWriteField(scratch1, |
560 offset, | 540 offset, |
561 name_reg, | 541 name_reg, |
562 receiver_reg, | 542 receiver_reg, |
563 kRAHasNotBeenSaved, | 543 kRAHasNotBeenSaved, |
564 kDontSaveFPRegs); | 544 kDontSaveFPRegs); |
565 } | 545 } |
566 | 546 |
567 // Return the value (register v0). | 547 // Return the value (register v0). |
| 548 ASSERT(value_reg.is(a0)); |
568 __ bind(&exit); | 549 __ bind(&exit); |
569 __ mov(v0, a0); | 550 __ mov(v0, a0); |
570 __ Ret(); | 551 __ Ret(); |
571 } | 552 } |
572 | 553 |
573 | 554 |
574 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 555 void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
575 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 556 Label* label, |
576 Handle<Code> code = (kind == Code::LOAD_IC) | 557 Handle<Name> name) { |
577 ? masm->isolate()->builtins()->LoadIC_Miss() | 558 if (!label->is_unused()) { |
578 : masm->isolate()->builtins()->KeyedLoadIC_Miss(); | 559 __ bind(label); |
579 __ Jump(code, RelocInfo::CODE_TARGET); | 560 __ li(this->name(), Operand(name)); |
| 561 } |
580 } | 562 } |
581 | 563 |
582 | 564 |
583 void StubCompiler::GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind) { | |
584 ASSERT(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC); | |
585 Handle<Code> code = (kind == Code::STORE_IC) | |
586 ? masm->isolate()->builtins()->StoreIC_Miss() | |
587 : masm->isolate()->builtins()->KeyedStoreIC_Miss(); | |
588 __ Jump(code, RelocInfo::CODE_TARGET); | |
589 } | |
590 | |
591 | |
592 static void GenerateCallFunction(MacroAssembler* masm, | 565 static void GenerateCallFunction(MacroAssembler* masm, |
593 Handle<Object> object, | 566 Handle<Object> object, |
594 const ParameterCount& arguments, | 567 const ParameterCount& arguments, |
595 Label* miss, | 568 Label* miss, |
596 Code::ExtraICState extra_ic_state) { | 569 Code::ExtraICState extra_ic_state) { |
597 // ----------- S t a t e ------------- | 570 // ----------- S t a t e ------------- |
598 // -- a0: receiver | 571 // -- a0: receiver |
599 // -- a1: function to call | 572 // -- a1: function to call |
600 // ----------------------------------- | 573 // ----------------------------------- |
601 // Check that the function really is a function. | 574 // Check that the function really is a function. |
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1057 | 1030 |
1058 __ bind(&done); | 1031 __ bind(&done); |
1059 | 1032 |
1060 __ sll(scratch1, wordoffset, 2); | 1033 __ sll(scratch1, wordoffset, 2); |
1061 __ addu(scratch1, dst, scratch1); | 1034 __ addu(scratch1, dst, scratch1); |
1062 __ sw(fval, MemOperand(scratch1, 0)); | 1035 __ sw(fval, MemOperand(scratch1, 0)); |
1063 } | 1036 } |
1064 } | 1037 } |
1065 | 1038 |
1066 | 1039 |
| 1040 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 1041 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1042 } |
| 1043 |
| 1044 |
1067 #undef __ | 1045 #undef __ |
1068 #define __ ACCESS_MASM(masm()) | 1046 #define __ ACCESS_MASM(masm()) |
1069 | 1047 |
1070 | 1048 |
1071 void StubCompiler::GenerateTailCall(Handle<Code> code) { | |
1072 __ Jump(code, RelocInfo::CODE_TARGET); | |
1073 } | |
1074 | |
1075 | |
1076 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1049 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
1077 Register object_reg, | 1050 Register object_reg, |
1078 Handle<JSObject> holder, | 1051 Handle<JSObject> holder, |
1079 Register holder_reg, | 1052 Register holder_reg, |
1080 Register scratch1, | 1053 Register scratch1, |
1081 Register scratch2, | 1054 Register scratch2, |
1082 Handle<Name> name, | 1055 Handle<Name> name, |
1083 int save_at_depth, | 1056 int save_at_depth, |
1084 Label* miss, | 1057 Label* miss, |
1085 PrototypeCheckType check) { | 1058 PrototypeCheckType check) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1183 // Return the register containing the holder. | 1156 // Return the register containing the holder. |
1184 return reg; | 1157 return reg; |
1185 } | 1158 } |
1186 | 1159 |
1187 | 1160 |
1188 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, | 1161 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, |
1189 Label* miss) { | 1162 Label* miss) { |
1190 if (!miss->is_unused()) { | 1163 if (!miss->is_unused()) { |
1191 __ Branch(success); | 1164 __ Branch(success); |
1192 __ bind(miss); | 1165 __ bind(miss); |
1193 GenerateLoadMiss(masm(), kind()); | 1166 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1194 } | 1167 } |
1195 } | 1168 } |
1196 | 1169 |
1197 | 1170 |
1198 Register BaseLoadStubCompiler::CallbackHandlerFrontend( | 1171 Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
1199 Handle<JSObject> object, | 1172 Handle<JSObject> object, |
1200 Register object_reg, | 1173 Register object_reg, |
1201 Handle<JSObject> holder, | 1174 Handle<JSObject> holder, |
1202 Handle<Name> name, | 1175 Handle<Name> name, |
1203 Label* success, | 1176 Label* success, |
(...skipping 1418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2622 // Handle call cache miss. | 2595 // Handle call cache miss. |
2623 __ bind(&miss); | 2596 __ bind(&miss); |
2624 __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); | 2597 __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); |
2625 GenerateMissBranch(); | 2598 GenerateMissBranch(); |
2626 | 2599 |
2627 // Return the generated code. | 2600 // Return the generated code. |
2628 return GetCode(Code::NORMAL, name); | 2601 return GetCode(Code::NORMAL, name); |
2629 } | 2602 } |
2630 | 2603 |
2631 | 2604 |
2632 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, | |
2633 int index, | |
2634 Handle<Map> transition, | |
2635 Handle<Name> name) { | |
2636 // ----------- S t a t e ------------- | |
2637 // -- a0 : value | |
2638 // -- a1 : receiver | |
2639 // -- a2 : name | |
2640 // -- ra : return address | |
2641 // ----------------------------------- | |
2642 Label miss; | |
2643 | |
2644 // Name register might be clobbered. | |
2645 GenerateStoreField(masm(), | |
2646 object, | |
2647 index, | |
2648 transition, | |
2649 name, | |
2650 a1, a2, a3, t0, | |
2651 &miss); | |
2652 __ bind(&miss); | |
2653 __ li(a2, Operand(Handle<Name>(name))); // Restore name. | |
2654 Handle<Code> ic = masm()->isolate()->builtins()->Builtins::StoreIC_Miss(); | |
2655 __ Jump(ic, RelocInfo::CODE_TARGET); | |
2656 | |
2657 // Return the generated code. | |
2658 return GetCode(transition.is_null() | |
2659 ? Code::FIELD | |
2660 : Code::MAP_TRANSITION, name); | |
2661 } | |
2662 | |
2663 | |
2664 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2605 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2665 Handle<Name> name, | 2606 Handle<Name> name, |
2666 Handle<JSObject> receiver, | 2607 Handle<JSObject> receiver, |
2667 Handle<JSObject> holder, | 2608 Handle<JSObject> holder, |
2668 Handle<ExecutableAccessorInfo> callback) { | 2609 Handle<ExecutableAccessorInfo> callback) { |
2669 // ----------- S t a t e ------------- | 2610 // ----------- S t a t e ------------- |
2670 // -- a0 : value | 2611 // -- a0 : value |
2671 // -- a1 : receiver | 2612 // -- a1 : receiver |
2672 // -- a2 : name | 2613 // -- a2 : name |
2673 // -- ra : return address | 2614 // -- ra : return address |
(...skipping 12 matching lines...) Expand all Loading... |
2686 __ Push(a3, a2, a0); | 2627 __ Push(a3, a2, a0); |
2687 | 2628 |
2688 // Do tail-call to the runtime system. | 2629 // Do tail-call to the runtime system. |
2689 ExternalReference store_callback_property = | 2630 ExternalReference store_callback_property = |
2690 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), | 2631 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), |
2691 masm()->isolate()); | 2632 masm()->isolate()); |
2692 __ TailCallExternalReference(store_callback_property, 4, 1); | 2633 __ TailCallExternalReference(store_callback_property, 4, 1); |
2693 | 2634 |
2694 // Handle store cache miss. | 2635 // Handle store cache miss. |
2695 __ bind(&miss); | 2636 __ bind(&miss); |
2696 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); | 2637 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2697 __ Jump(ic, RelocInfo::CODE_TARGET); | |
2698 | 2638 |
2699 // Return the generated code. | 2639 // Return the generated code. |
2700 return GetCode(Code::CALLBACKS, name); | 2640 return GetICCode(kind(), Code::CALLBACKS, name); |
2701 } | 2641 } |
2702 | 2642 |
2703 | 2643 |
2704 #undef __ | 2644 #undef __ |
2705 #define __ ACCESS_MASM(masm) | 2645 #define __ ACCESS_MASM(masm) |
2706 | 2646 |
2707 | 2647 |
2708 void StoreStubCompiler::GenerateStoreViaSetter( | 2648 void StoreStubCompiler::GenerateStoreViaSetter( |
2709 MacroAssembler* masm, | 2649 MacroAssembler* masm, |
2710 Handle<JSFunction> setter) { | 2650 Handle<JSFunction> setter) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2760 // ----------------------------------- | 2700 // ----------------------------------- |
2761 Label miss; | 2701 Label miss; |
2762 | 2702 |
2763 // Check that the maps haven't changed. | 2703 // Check that the maps haven't changed. |
2764 __ JumpIfSmi(a1, &miss); | 2704 __ JumpIfSmi(a1, &miss); |
2765 CheckPrototypes(receiver, a1, holder, a3, t0, t1, name, &miss); | 2705 CheckPrototypes(receiver, a1, holder, a3, t0, t1, name, &miss); |
2766 | 2706 |
2767 GenerateStoreViaSetter(masm(), setter); | 2707 GenerateStoreViaSetter(masm(), setter); |
2768 | 2708 |
2769 __ bind(&miss); | 2709 __ bind(&miss); |
2770 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); | 2710 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2771 __ Jump(ic, RelocInfo::CODE_TARGET); | |
2772 | 2711 |
2773 // Return the generated code. | 2712 // Return the generated code. |
2774 return GetCode(Code::CALLBACKS, name); | 2713 return GetICCode(kind(), Code::CALLBACKS, name); |
2775 } | 2714 } |
2776 | 2715 |
2777 | 2716 |
2778 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 2717 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( |
2779 Handle<JSObject> receiver, | 2718 Handle<JSObject> receiver, |
2780 Handle<Name> name) { | 2719 Handle<Name> name) { |
2781 // ----------- S t a t e ------------- | 2720 // ----------- S t a t e ------------- |
2782 // -- a0 : value | 2721 // -- a0 : value |
2783 // -- a1 : receiver | 2722 // -- a1 : receiver |
2784 // -- a2 : name | 2723 // -- a2 : name |
2785 // -- ra : return address | 2724 // -- ra : return address |
2786 // ----------------------------------- | 2725 // ----------------------------------- |
2787 Label miss; | 2726 Label miss; |
2788 | 2727 |
2789 // Check that the map of the object hasn't changed. | 2728 // Check that the map of the object hasn't changed. |
2790 __ CheckMap(a1, a3, Handle<Map>(receiver->map()), &miss, | 2729 __ CheckMap(a1, a3, Handle<Map>(receiver->map()), &miss, |
2791 DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); | 2730 DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
2792 | 2731 |
2793 // Perform global security token check if needed. | 2732 // Perform global security token check if needed. |
2794 if (receiver->IsJSGlobalProxy()) { | 2733 if (receiver->IsJSGlobalProxy()) { |
2795 __ CheckAccessGlobalProxy(a1, a3, &miss); | 2734 __ CheckAccessGlobalProxy(a1, a3, &miss); |
2796 } | 2735 } |
2797 | 2736 |
2798 // Stub is never generated for non-global objects that require access | 2737 // Stub is never generated for non-global objects that require access |
2799 // checks. | 2738 // checks. |
2800 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); | 2739 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); |
2801 | 2740 |
2802 __ Push(a1, a2, a0); // Receiver, name, value. | 2741 __ Push(a1, a2, a0); // Receiver, name, value. |
2803 | 2742 |
2804 __ li(a0, Operand(Smi::FromInt(strict_mode_))); | 2743 __ li(a0, Operand(Smi::FromInt(strict_mode()))); |
2805 __ push(a0); // Strict mode. | 2744 __ push(a0); // Strict mode. |
2806 | 2745 |
2807 // Do tail-call to the runtime system. | 2746 // Do tail-call to the runtime system. |
2808 ExternalReference store_ic_property = | 2747 ExternalReference store_ic_property = |
2809 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), | 2748 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), |
2810 masm()->isolate()); | 2749 masm()->isolate()); |
2811 __ TailCallExternalReference(store_ic_property, 4, 1); | 2750 __ TailCallExternalReference(store_ic_property, 4, 1); |
2812 | 2751 |
2813 // Handle store cache miss. | 2752 // Handle store cache miss. |
2814 __ bind(&miss); | 2753 __ bind(&miss); |
2815 Handle<Code> ic = masm()->isolate()->builtins()->Builtins::StoreIC_Miss(); | 2754 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2816 __ Jump(ic, RelocInfo::CODE_TARGET); | |
2817 | 2755 |
2818 // Return the generated code. | 2756 // Return the generated code. |
2819 return GetCode(Code::INTERCEPTOR, name); | 2757 return GetICCode(kind(), Code::INTERCEPTOR, name); |
2820 } | 2758 } |
2821 | 2759 |
2822 | 2760 |
2823 Handle<Code> StoreStubCompiler::CompileStoreGlobal( | 2761 Handle<Code> StoreStubCompiler::CompileStoreGlobal( |
2824 Handle<GlobalObject> object, | 2762 Handle<GlobalObject> object, |
2825 Handle<JSGlobalPropertyCell> cell, | 2763 Handle<JSGlobalPropertyCell> cell, |
2826 Handle<Name> name) { | 2764 Handle<Name> name) { |
2827 // ----------- S t a t e ------------- | 2765 // ----------- S t a t e ------------- |
2828 // -- a0 : value | 2766 // -- a0 : value |
2829 // -- a1 : receiver | 2767 // -- a1 : receiver |
(...skipping 20 matching lines...) Expand all Loading... |
2850 __ mov(v0, a0); // Stored value must be returned in v0. | 2788 __ mov(v0, a0); // Stored value must be returned in v0. |
2851 // Cells are always rescanned, so no write barrier here. | 2789 // Cells are always rescanned, so no write barrier here. |
2852 | 2790 |
2853 Counters* counters = masm()->isolate()->counters(); | 2791 Counters* counters = masm()->isolate()->counters(); |
2854 __ IncrementCounter(counters->named_store_global_inline(), 1, a1, a3); | 2792 __ IncrementCounter(counters->named_store_global_inline(), 1, a1, a3); |
2855 __ Ret(); | 2793 __ Ret(); |
2856 | 2794 |
2857 // Handle store cache miss. | 2795 // Handle store cache miss. |
2858 __ bind(&miss); | 2796 __ bind(&miss); |
2859 __ IncrementCounter(counters->named_store_global_inline_miss(), 1, a1, a3); | 2797 __ IncrementCounter(counters->named_store_global_inline_miss(), 1, a1, a3); |
2860 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); | 2798 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2861 __ Jump(ic, RelocInfo::CODE_TARGET); | |
2862 | 2799 |
2863 // Return the generated code. | 2800 // Return the generated code. |
2864 return GetCode(Code::NORMAL, name); | 2801 return GetICCode(kind(), Code::NORMAL, name); |
2865 } | 2802 } |
2866 | 2803 |
2867 | 2804 |
2868 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( | 2805 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( |
2869 Handle<JSObject> object, | 2806 Handle<JSObject> object, |
2870 Handle<JSObject> last, | 2807 Handle<JSObject> last, |
2871 Handle<Name> name, | 2808 Handle<Name> name, |
2872 Handle<GlobalObject> global) { | 2809 Handle<GlobalObject> global) { |
2873 Label success; | 2810 Label success; |
2874 | 2811 |
(...skipping 16 matching lines...) Expand all Loading... |
2891 } | 2828 } |
2892 | 2829 |
2893 | 2830 |
2894 Register* KeyedLoadStubCompiler::registers() { | 2831 Register* KeyedLoadStubCompiler::registers() { |
2895 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 2832 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
2896 static Register registers[] = { a1, a0, a2, a3, t0, t1 }; | 2833 static Register registers[] = { a1, a0, a2, a3, t0, t1 }; |
2897 return registers; | 2834 return registers; |
2898 } | 2835 } |
2899 | 2836 |
2900 | 2837 |
| 2838 Register* StoreStubCompiler::registers() { |
| 2839 // receiver, name, value, scratch1, scratch2, scratch3. |
| 2840 static Register registers[] = { a1, a2, a0, a3, t0, t1 }; |
| 2841 return registers; |
| 2842 } |
| 2843 |
| 2844 |
| 2845 Register* KeyedStoreStubCompiler::registers() { |
| 2846 // receiver, name, value, scratch1, scratch2, scratch3. |
| 2847 static Register registers[] = { a2, a1, a0, a3, t0, t1 }; |
| 2848 return registers; |
| 2849 } |
| 2850 |
| 2851 |
2901 void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name, | 2852 void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name, |
2902 Register name_reg, | 2853 Register name_reg, |
2903 Label* miss) { | 2854 Label* miss) { |
2904 __ Branch(miss, ne, name_reg, Operand(name)); | 2855 __ Branch(miss, ne, name_reg, Operand(name)); |
2905 } | 2856 } |
2906 | 2857 |
2907 | 2858 |
| 2859 void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name, |
| 2860 Register name_reg, |
| 2861 Label* miss) { |
| 2862 __ Branch(miss, ne, name_reg, Operand(name)); |
| 2863 } |
| 2864 |
| 2865 |
2908 #undef __ | 2866 #undef __ |
2909 #define __ ACCESS_MASM(masm) | 2867 #define __ ACCESS_MASM(masm) |
2910 | 2868 |
2911 | 2869 |
2912 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 2870 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, |
2913 Handle<JSFunction> getter) { | 2871 Handle<JSFunction> getter) { |
2914 // ----------- S t a t e ------------- | 2872 // ----------- S t a t e ------------- |
2915 // -- a0 : receiver | 2873 // -- a0 : receiver |
2916 // -- a2 : name | 2874 // -- a2 : name |
2917 // -- ra : return address | 2875 // -- ra : return address |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2991 Handle<Code> stub = KeyedLoadFastElementStub( | 2949 Handle<Code> stub = KeyedLoadFastElementStub( |
2992 receiver_map->instance_type() == JS_ARRAY_TYPE, | 2950 receiver_map->instance_type() == JS_ARRAY_TYPE, |
2993 elements_kind).GetCode(isolate()); | 2951 elements_kind).GetCode(isolate()); |
2994 __ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK); | 2952 __ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK); |
2995 } else { | 2953 } else { |
2996 Handle<Code> stub = | 2954 Handle<Code> stub = |
2997 KeyedLoadDictionaryElementStub().GetCode(isolate()); | 2955 KeyedLoadDictionaryElementStub().GetCode(isolate()); |
2998 __ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK); | 2956 __ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK); |
2999 } | 2957 } |
3000 | 2958 |
3001 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | 2959 TailCallBuiltin(masm(), MissBuiltin(kind())); |
3002 __ Jump(ic, RelocInfo::CODE_TARGET); | |
3003 | 2960 |
3004 // Return the generated code. | 2961 // Return the generated code. |
3005 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); | 2962 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); |
3006 } | 2963 } |
3007 | 2964 |
3008 | 2965 |
3009 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( | 2966 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( |
3010 MapHandleList* receiver_maps, | 2967 MapHandleList* receiver_maps, |
3011 CodeHandleList* handlers, | 2968 CodeHandleList* handlers, |
3012 Handle<Name> name, | 2969 Handle<Name> name, |
3013 Code::StubType type, | 2970 Code::StubType type, |
3014 IcCheckType check) { | 2971 IcCheckType check) { |
3015 Label miss; | 2972 Label miss; |
3016 | 2973 |
3017 if (check == PROPERTY) { | 2974 if (check == PROPERTY) { |
3018 GenerateNameCheck(name, this->name(), &miss); | 2975 GenerateNameCheck(name, this->name(), &miss); |
3019 } | 2976 } |
3020 | 2977 |
3021 __ JumpIfSmi(receiver(), &miss); | 2978 __ JumpIfSmi(receiver(), &miss); |
3022 Register map_reg = scratch1(); | 2979 Register map_reg = scratch1(); |
3023 | 2980 |
3024 int receiver_count = receiver_maps->length(); | 2981 int receiver_count = receiver_maps->length(); |
3025 __ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); | 2982 __ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
3026 for (int current = 0; current < receiver_count; ++current) { | 2983 for (int current = 0; current < receiver_count; ++current) { |
3027 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, | 2984 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, |
3028 eq, map_reg, Operand(receiver_maps->at(current))); | 2985 eq, map_reg, Operand(receiver_maps->at(current))); |
3029 } | 2986 } |
3030 | 2987 |
3031 __ bind(&miss); | 2988 __ bind(&miss); |
3032 GenerateLoadMiss(masm(), kind()); | 2989 TailCallBuiltin(masm(), MissBuiltin(kind())); |
3033 | 2990 |
3034 // Return the generated code. | 2991 // Return the generated code. |
3035 InlineCacheState state = | 2992 InlineCacheState state = |
3036 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; | 2993 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; |
3037 return GetICCode(kind(), type, name, state); | 2994 return GetICCode(kind(), type, name, state); |
3038 } | 2995 } |
3039 | 2996 |
3040 | 2997 |
3041 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, | |
3042 int index, | |
3043 Handle<Map> transition, | |
3044 Handle<Name> name) { | |
3045 // ----------- S t a t e ------------- | |
3046 // -- a0 : value | |
3047 // -- a1 : key | |
3048 // -- a2 : receiver | |
3049 // -- ra : return address | |
3050 // ----------------------------------- | |
3051 | |
3052 Label miss; | |
3053 | |
3054 Counters* counters = masm()->isolate()->counters(); | |
3055 __ IncrementCounter(counters->keyed_store_field(), 1, a3, t0); | |
3056 | |
3057 // Check that the name has not changed. | |
3058 __ Branch(&miss, ne, a1, Operand(name)); | |
3059 | |
3060 // a3 is used as scratch register. a1 and a2 keep their values if a jump to | |
3061 // the miss label is generated. | |
3062 GenerateStoreField(masm(), | |
3063 object, | |
3064 index, | |
3065 transition, | |
3066 name, | |
3067 a2, a1, a3, t0, | |
3068 &miss); | |
3069 __ bind(&miss); | |
3070 | |
3071 __ DecrementCounter(counters->keyed_store_field(), 1, a3, t0); | |
3072 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); | |
3073 __ Jump(ic, RelocInfo::CODE_TARGET); | |
3074 | |
3075 // Return the generated code. | |
3076 return GetCode(transition.is_null() | |
3077 ? Code::FIELD | |
3078 : Code::MAP_TRANSITION, name); | |
3079 } | |
3080 | |
3081 | |
3082 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( | 2998 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( |
3083 Handle<Map> receiver_map) { | 2999 Handle<Map> receiver_map) { |
3084 // ----------- S t a t e ------------- | 3000 // ----------- S t a t e ------------- |
3085 // -- a0 : value | 3001 // -- a0 : value |
3086 // -- a1 : key | 3002 // -- a1 : key |
3087 // -- a2 : receiver | 3003 // -- a2 : receiver |
3088 // -- ra : return address | 3004 // -- ra : return address |
3089 // -- a3 : scratch | 3005 // -- a3 : scratch |
3090 // ----------------------------------- | 3006 // ----------------------------------- |
3091 ElementsKind elements_kind = receiver_map->elements_kind(); | 3007 ElementsKind elements_kind = receiver_map->elements_kind(); |
3092 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 3008 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
3093 Handle<Code> stub = | 3009 Handle<Code> stub = |
3094 KeyedStoreElementStub(is_js_array, | 3010 KeyedStoreElementStub(is_js_array, |
3095 elements_kind, | 3011 elements_kind, |
3096 store_mode_).GetCode(isolate()); | 3012 store_mode_).GetCode(isolate()); |
3097 | 3013 |
3098 __ DispatchMap(a2, a3, receiver_map, stub, DO_SMI_CHECK); | 3014 __ DispatchMap(a2, a3, receiver_map, stub, DO_SMI_CHECK); |
3099 | 3015 |
3100 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 3016 TailCallBuiltin(masm(), MissBuiltin(kind())); |
3101 __ Jump(ic, RelocInfo::CODE_TARGET); | |
3102 | 3017 |
3103 // Return the generated code. | 3018 // Return the generated code. |
3104 return GetCode(Code::NORMAL, factory()->empty_string()); | 3019 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); |
3105 } | 3020 } |
3106 | 3021 |
3107 | 3022 |
3108 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 3023 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( |
3109 MapHandleList* receiver_maps, | 3024 MapHandleList* receiver_maps, |
3110 CodeHandleList* handler_stubs, | 3025 CodeHandleList* handler_stubs, |
3111 MapHandleList* transitioned_maps) { | 3026 MapHandleList* transitioned_maps) { |
3112 // ----------- S t a t e ------------- | 3027 // ----------- S t a t e ------------- |
3113 // -- a0 : value | 3028 // -- a0 : value |
3114 // -- a1 : key | 3029 // -- a1 : key |
(...skipping 13 matching lines...) Expand all Loading... |
3128 } else { | 3043 } else { |
3129 Label next_map; | 3044 Label next_map; |
3130 __ Branch(&next_map, ne, a3, Operand(receiver_maps->at(i))); | 3045 __ Branch(&next_map, ne, a3, Operand(receiver_maps->at(i))); |
3131 __ li(a3, Operand(transitioned_maps->at(i))); | 3046 __ li(a3, Operand(transitioned_maps->at(i))); |
3132 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET); | 3047 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
3133 __ bind(&next_map); | 3048 __ bind(&next_map); |
3134 } | 3049 } |
3135 } | 3050 } |
3136 | 3051 |
3137 __ bind(&miss); | 3052 __ bind(&miss); |
3138 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 3053 TailCallBuiltin(masm(), MissBuiltin(kind())); |
3139 __ Jump(miss_ic, RelocInfo::CODE_TARGET); | |
3140 | 3054 |
3141 // Return the generated code. | 3055 // Return the generated code. |
3142 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 3056 return GetICCode( |
| 3057 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
3143 } | 3058 } |
3144 | 3059 |
3145 | 3060 |
3146 Handle<Code> ConstructStubCompiler::CompileConstructStub( | 3061 Handle<Code> ConstructStubCompiler::CompileConstructStub( |
3147 Handle<JSFunction> function) { | 3062 Handle<JSFunction> function) { |
3148 // a0 : argc | 3063 // a0 : argc |
3149 // a1 : constructor | 3064 // a1 : constructor |
3150 // ra : return address | 3065 // ra : return address |
3151 // [sp] : last argument | 3066 // [sp] : last argument |
3152 Label generic_stub_call; | 3067 Label generic_stub_call; |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3320 __ bind(&slow); | 3235 __ bind(&slow); |
3321 __ IncrementCounter( | 3236 __ IncrementCounter( |
3322 masm->isolate()->counters()->keyed_load_external_array_slow(), | 3237 masm->isolate()->counters()->keyed_load_external_array_slow(), |
3323 1, a2, a3); | 3238 1, a2, a3); |
3324 // Entry registers are intact. | 3239 // Entry registers are intact. |
3325 // ---------- S t a t e -------------- | 3240 // ---------- S t a t e -------------- |
3326 // -- ra : return address | 3241 // -- ra : return address |
3327 // -- a0 : key | 3242 // -- a0 : key |
3328 // -- a1 : receiver | 3243 // -- a1 : receiver |
3329 // ----------------------------------- | 3244 // ----------------------------------- |
3330 Handle<Code> slow_ic = | 3245 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); |
3331 masm->isolate()->builtins()->KeyedLoadIC_Slow(); | |
3332 __ Jump(slow_ic, RelocInfo::CODE_TARGET); | |
3333 | 3246 |
3334 // Miss case, call the runtime. | 3247 // Miss case, call the runtime. |
3335 __ bind(&miss_force_generic); | 3248 __ bind(&miss_force_generic); |
3336 | 3249 |
3337 // ---------- S t a t e -------------- | 3250 // ---------- S t a t e -------------- |
3338 // -- ra : return address | 3251 // -- ra : return address |
3339 // -- a0 : key | 3252 // -- a0 : key |
3340 // -- a1 : receiver | 3253 // -- a1 : receiver |
3341 // ----------------------------------- | 3254 // ----------------------------------- |
3342 | 3255 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
3343 Handle<Code> miss_ic = | |
3344 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | |
3345 __ Jump(miss_ic, RelocInfo::CODE_TARGET); | |
3346 } | 3256 } |
3347 | 3257 |
3348 | 3258 |
3349 static bool IsElementTypeSigned(ElementsKind elements_kind) { | 3259 static bool IsElementTypeSigned(ElementsKind elements_kind) { |
3350 switch (elements_kind) { | 3260 switch (elements_kind) { |
3351 case EXTERNAL_BYTE_ELEMENTS: | 3261 case EXTERNAL_BYTE_ELEMENTS: |
3352 case EXTERNAL_SHORT_ELEMENTS: | 3262 case EXTERNAL_SHORT_ELEMENTS: |
3353 case EXTERNAL_INT_ELEMENTS: | 3263 case EXTERNAL_INT_ELEMENTS: |
3354 return true; | 3264 return true; |
3355 | 3265 |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3789 __ bind(&slow); | 3699 __ bind(&slow); |
3790 __ IncrementCounter( | 3700 __ IncrementCounter( |
3791 masm->isolate()->counters()->keyed_load_external_array_slow(), | 3701 masm->isolate()->counters()->keyed_load_external_array_slow(), |
3792 1, a2, a3); | 3702 1, a2, a3); |
3793 // Entry registers are intact. | 3703 // Entry registers are intact. |
3794 // ---------- S t a t e -------------- | 3704 // ---------- S t a t e -------------- |
3795 // -- ra : return address | 3705 // -- ra : return address |
3796 // -- a0 : key | 3706 // -- a0 : key |
3797 // -- a1 : receiver | 3707 // -- a1 : receiver |
3798 // ----------------------------------- | 3708 // ----------------------------------- |
3799 Handle<Code> slow_ic = | 3709 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3800 masm->isolate()->builtins()->KeyedStoreIC_Slow(); | |
3801 __ Jump(slow_ic, RelocInfo::CODE_TARGET); | |
3802 | 3710 |
3803 // Miss case, call the runtime. | 3711 // Miss case, call the runtime. |
3804 __ bind(&miss_force_generic); | 3712 __ bind(&miss_force_generic); |
3805 | 3713 |
3806 // ---------- S t a t e -------------- | 3714 // ---------- S t a t e -------------- |
3807 // -- ra : return address | 3715 // -- ra : return address |
3808 // -- a0 : key | 3716 // -- a0 : key |
3809 // -- a1 : receiver | 3717 // -- a1 : receiver |
3810 // ----------------------------------- | 3718 // ----------------------------------- |
3811 | 3719 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric); |
3812 Handle<Code> miss_ic = | |
3813 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | |
3814 __ Jump(miss_ic, RelocInfo::CODE_TARGET); | |
3815 } | 3720 } |
3816 | 3721 |
3817 | 3722 |
3818 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 3723 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
3819 MacroAssembler* masm, | 3724 MacroAssembler* masm, |
3820 bool is_js_array, | 3725 bool is_js_array, |
3821 ElementsKind elements_kind, | 3726 ElementsKind elements_kind, |
3822 KeyedAccessStoreMode store_mode) { | 3727 KeyedAccessStoreMode store_mode) { |
3823 // ----------- S t a t e ------------- | 3728 // ----------- S t a t e ------------- |
3824 // -- a0 : value | 3729 // -- a0 : value |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3895 scratch, // Address. | 3800 scratch, // Address. |
3896 receiver_reg, // Value. | 3801 receiver_reg, // Value. |
3897 kRAHasNotBeenSaved, | 3802 kRAHasNotBeenSaved, |
3898 kDontSaveFPRegs); | 3803 kDontSaveFPRegs); |
3899 } | 3804 } |
3900 // value_reg (a0) is preserved. | 3805 // value_reg (a0) is preserved. |
3901 // Done. | 3806 // Done. |
3902 __ Ret(); | 3807 __ Ret(); |
3903 | 3808 |
3904 __ bind(&miss_force_generic); | 3809 __ bind(&miss_force_generic); |
3905 Handle<Code> ic = | 3810 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric); |
3906 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | |
3907 __ Jump(ic, RelocInfo::CODE_TARGET); | |
3908 | 3811 |
3909 __ bind(&transition_elements_kind); | 3812 __ bind(&transition_elements_kind); |
3910 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 3813 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss); |
3911 __ Jump(ic_miss, RelocInfo::CODE_TARGET); | |
3912 | 3814 |
3913 if (is_js_array && IsGrowStoreMode(store_mode)) { | 3815 if (is_js_array && IsGrowStoreMode(store_mode)) { |
3914 // Grow the array by a single element if possible. | 3816 // Grow the array by a single element if possible. |
3915 __ bind(&grow); | 3817 __ bind(&grow); |
3916 | 3818 |
3917 // Make sure the array is only growing by a single element, anything else | 3819 // Make sure the array is only growing by a single element, anything else |
3918 // must be handled by the runtime. | 3820 // must be handled by the runtime. |
3919 __ Branch(&miss_force_generic, ne, key_reg, Operand(scratch)); | 3821 __ Branch(&miss_force_generic, ne, key_reg, Operand(scratch)); |
3920 | 3822 |
3921 // Check for the empty array, and preallocate a small backing store if | 3823 // Check for the empty array, and preallocate a small backing store if |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3965 | 3867 |
3966 __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); | 3868 __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); |
3967 __ Branch(&slow, hs, length_reg, Operand(scratch)); | 3869 __ Branch(&slow, hs, length_reg, Operand(scratch)); |
3968 | 3870 |
3969 // Grow the array and finish the store. | 3871 // Grow the array and finish the store. |
3970 __ Addu(length_reg, length_reg, Operand(Smi::FromInt(1))); | 3872 __ Addu(length_reg, length_reg, Operand(Smi::FromInt(1))); |
3971 __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); | 3873 __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); |
3972 __ jmp(&finish_store); | 3874 __ jmp(&finish_store); |
3973 | 3875 |
3974 __ bind(&slow); | 3876 __ bind(&slow); |
3975 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); | 3877 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3976 __ Jump(ic_slow, RelocInfo::CODE_TARGET); | |
3977 } | 3878 } |
3978 } | 3879 } |
3979 | 3880 |
3980 | 3881 |
3981 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( | 3882 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( |
3982 MacroAssembler* masm, | 3883 MacroAssembler* masm, |
3983 bool is_js_array, | 3884 bool is_js_array, |
3984 KeyedAccessStoreMode store_mode) { | 3885 KeyedAccessStoreMode store_mode) { |
3985 // ----------- S t a t e ------------- | 3886 // ----------- S t a t e ------------- |
3986 // -- a0 : value | 3887 // -- a0 : value |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4042 scratch2, | 3943 scratch2, |
4043 scratch3, | 3944 scratch3, |
4044 scratch4, | 3945 scratch4, |
4045 &transition_elements_kind); | 3946 &transition_elements_kind); |
4046 | 3947 |
4047 __ Ret(USE_DELAY_SLOT); | 3948 __ Ret(USE_DELAY_SLOT); |
4048 __ mov(v0, value_reg); // In delay slot. | 3949 __ mov(v0, value_reg); // In delay slot. |
4049 | 3950 |
4050 // Handle store cache miss, replacing the ic with the generic stub. | 3951 // Handle store cache miss, replacing the ic with the generic stub. |
4051 __ bind(&miss_force_generic); | 3952 __ bind(&miss_force_generic); |
4052 Handle<Code> ic = | 3953 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric); |
4053 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | |
4054 __ Jump(ic, RelocInfo::CODE_TARGET); | |
4055 | 3954 |
4056 __ bind(&transition_elements_kind); | 3955 __ bind(&transition_elements_kind); |
4057 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 3956 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss); |
4058 __ Jump(ic_miss, RelocInfo::CODE_TARGET); | |
4059 | 3957 |
4060 if (is_js_array && IsGrowStoreMode(store_mode)) { | 3958 if (is_js_array && IsGrowStoreMode(store_mode)) { |
4061 // Grow the array by a single element if possible. | 3959 // Grow the array by a single element if possible. |
4062 __ bind(&grow); | 3960 __ bind(&grow); |
4063 | 3961 |
4064 // Make sure the array is only growing by a single element, anything else | 3962 // Make sure the array is only growing by a single element, anything else |
4065 // must be handled by the runtime. | 3963 // must be handled by the runtime. |
4066 __ Branch(&miss_force_generic, ne, key_reg, Operand(scratch1)); | 3964 __ Branch(&miss_force_generic, ne, key_reg, Operand(scratch1)); |
4067 | 3965 |
4068 // Transition on values that can't be stored in a FixedDoubleArray. | 3966 // Transition on values that can't be stored in a FixedDoubleArray. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4131 __ lw(scratch1, | 4029 __ lw(scratch1, |
4132 FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset)); | 4030 FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset)); |
4133 __ Branch(&slow, hs, length_reg, Operand(scratch1)); | 4031 __ Branch(&slow, hs, length_reg, Operand(scratch1)); |
4134 | 4032 |
4135 // Grow the array and finish the store. | 4033 // Grow the array and finish the store. |
4136 __ Addu(length_reg, length_reg, Operand(Smi::FromInt(1))); | 4034 __ Addu(length_reg, length_reg, Operand(Smi::FromInt(1))); |
4137 __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); | 4035 __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); |
4138 __ jmp(&finish_store); | 4036 __ jmp(&finish_store); |
4139 | 4037 |
4140 __ bind(&slow); | 4038 __ bind(&slow); |
4141 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); | 4039 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
4142 __ Jump(ic_slow, RelocInfo::CODE_TARGET); | |
4143 } | 4040 } |
4144 } | 4041 } |
4145 | 4042 |
4146 | 4043 |
4147 #undef __ | 4044 #undef __ |
4148 | 4045 |
4149 } } // namespace v8::internal | 4046 } } // namespace v8::internal |
4150 | 4047 |
4151 #endif // V8_TARGET_ARCH_MIPS | 4048 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |