OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
6 | 6 |
7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 __ Branch(&new_object, ne, a1, Operand(a3)); | 326 __ Branch(&new_object, ne, a1, Operand(a3)); |
327 | 327 |
328 // 5. Allocate a JSValue wrapper for the number. | 328 // 5. Allocate a JSValue wrapper for the number. |
329 __ AllocateJSValue(v0, a1, a0, a2, t0, &new_object); | 329 __ AllocateJSValue(v0, a1, a0, a2, t0, &new_object); |
330 __ Ret(); | 330 __ Ret(); |
331 | 331 |
332 // 6. Fallback to the runtime to create new object. | 332 // 6. Fallback to the runtime to create new object. |
333 __ bind(&new_object); | 333 __ bind(&new_object); |
334 { | 334 { |
335 FrameScope scope(masm, StackFrame::INTERNAL); | 335 FrameScope scope(masm, StackFrame::INTERNAL); |
336 __ Push(a0, a1, a3); // first argument, constructor, new target | 336 __ Push(a0); // first argument |
337 __ CallRuntime(Runtime::kNewObject); | 337 FastNewObjectStub stub(masm->isolate()); |
| 338 __ CallStub(&stub); |
338 __ Pop(a0); | 339 __ Pop(a0); |
339 } | 340 } |
340 __ Ret(USE_DELAY_SLOT); | 341 __ Ret(USE_DELAY_SLOT); |
341 __ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset)); // In delay slot | 342 __ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset)); // In delay slot |
342 } | 343 } |
343 | 344 |
344 | 345 |
345 // static | 346 // static |
346 void Builtins::Generate_StringConstructor(MacroAssembler* masm) { | 347 void Builtins::Generate_StringConstructor(MacroAssembler* masm) { |
347 // ----------- S t a t e ------------- | 348 // ----------- S t a t e ------------- |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 __ Branch(&new_object, ne, a1, Operand(a3)); | 455 __ Branch(&new_object, ne, a1, Operand(a3)); |
455 | 456 |
456 // 5. Allocate a JSValue wrapper for the string. | 457 // 5. Allocate a JSValue wrapper for the string. |
457 __ AllocateJSValue(v0, a1, a0, a2, t0, &new_object); | 458 __ AllocateJSValue(v0, a1, a0, a2, t0, &new_object); |
458 __ Ret(); | 459 __ Ret(); |
459 | 460 |
460 // 6. Fallback to the runtime to create new object. | 461 // 6. Fallback to the runtime to create new object. |
461 __ bind(&new_object); | 462 __ bind(&new_object); |
462 { | 463 { |
463 FrameScope scope(masm, StackFrame::INTERNAL); | 464 FrameScope scope(masm, StackFrame::INTERNAL); |
464 __ Push(a0, a1, a3); // first argument, constructor, new target | 465 __ Push(a0); // first argument |
465 __ CallRuntime(Runtime::kNewObject); | 466 FastNewObjectStub stub(masm->isolate()); |
| 467 __ CallStub(&stub); |
466 __ Pop(a0); | 468 __ Pop(a0); |
467 } | 469 } |
468 __ Ret(USE_DELAY_SLOT); | 470 __ Ret(USE_DELAY_SLOT); |
469 __ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset)); // In delay slot | 471 __ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset)); // In delay slot |
470 } | 472 } |
471 | 473 |
472 static void GenerateTailCallToSharedCode(MacroAssembler* masm) { | 474 static void GenerateTailCallToSharedCode(MacroAssembler* masm) { |
473 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 475 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
474 __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset)); | 476 __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset)); |
475 __ Addu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag)); | 477 __ Addu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag)); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
537 // Enter a construct frame. | 539 // Enter a construct frame. |
538 { | 540 { |
539 FrameScope scope(masm, StackFrame::CONSTRUCT); | 541 FrameScope scope(masm, StackFrame::CONSTRUCT); |
540 | 542 |
541 // Preserve the incoming parameters on the stack. | 543 // Preserve the incoming parameters on the stack. |
542 __ AssertUndefinedOrAllocationSite(a2, t0); | 544 __ AssertUndefinedOrAllocationSite(a2, t0); |
543 __ SmiTag(a0); | 545 __ SmiTag(a0); |
544 __ Push(a2, a0); | 546 __ Push(a2, a0); |
545 | 547 |
546 if (create_implicit_receiver) { | 548 if (create_implicit_receiver) { |
547 // Try to allocate the object without transitioning into C code. If any of | 549 // Allocate the new receiver object. |
548 // the preconditions is not met, the code bails out to the runtime call. | 550 __ Push(a1, a3); |
549 Label rt_call, allocated; | 551 FastNewObjectStub stub(masm->isolate()); |
550 if (FLAG_inline_new) { | 552 __ CallStub(&stub); |
551 // Verify that the new target is a JSFunction. | |
552 __ GetObjectType(a3, t1, t0); | |
553 __ Branch(&rt_call, ne, t0, Operand(JS_FUNCTION_TYPE)); | |
554 | |
555 // Load the initial map and verify that it is in fact a map. | |
556 // a3: new target | |
557 __ lw(a2, | |
558 FieldMemOperand(a3, JSFunction::kPrototypeOrInitialMapOffset)); | |
559 __ JumpIfSmi(a2, &rt_call); | |
560 __ GetObjectType(a2, t5, t4); | |
561 __ Branch(&rt_call, ne, t4, Operand(MAP_TYPE)); | |
562 | |
563 // Fall back to runtime if the expected base constructor and base | |
564 // constructor differ. | |
565 __ lw(t1, FieldMemOperand(a2, Map::kConstructorOrBackPointerOffset)); | |
566 __ Branch(&rt_call, ne, a1, Operand(t1)); | |
567 | |
568 // Check that the constructor is not constructing a JSFunction (see | |
569 // comments in Runtime_NewObject in runtime.cc). In which case the | |
570 // initial map's instance type would be JS_FUNCTION_TYPE. | |
571 // a1: constructor function | |
572 // a2: initial map | |
573 __ lbu(t5, FieldMemOperand(a2, Map::kInstanceTypeOffset)); | |
574 __ Branch(&rt_call, eq, t5, Operand(JS_FUNCTION_TYPE)); | |
575 | |
576 // Now allocate the JSObject on the heap. | |
577 // a1: constructor function | |
578 // a2: initial map | |
579 // a3: new target | |
580 __ lbu(t3, FieldMemOperand(a2, Map::kInstanceSizeOffset)); | |
581 | |
582 __ Allocate(t3, t4, t3, t6, &rt_call, SIZE_IN_WORDS); | |
583 | |
584 // Allocated the JSObject, now initialize the fields. Map is set to | |
585 // initial map and properties and elements are set to empty fixed array. | |
586 // a1: constructor function | |
587 // a2: initial map | |
588 // a3: new target | |
589 // t4: JSObject (not HeapObject tagged - the actual address). | |
590 // t3: start of next object | |
591 __ LoadRoot(t6, Heap::kEmptyFixedArrayRootIndex); | |
592 __ mov(t5, t4); | |
593 STATIC_ASSERT(0 * kPointerSize == JSObject::kMapOffset); | |
594 __ sw(a2, MemOperand(t5, JSObject::kMapOffset)); | |
595 STATIC_ASSERT(1 * kPointerSize == JSObject::kPropertiesOffset); | |
596 __ sw(t6, MemOperand(t5, JSObject::kPropertiesOffset)); | |
597 STATIC_ASSERT(2 * kPointerSize == JSObject::kElementsOffset); | |
598 __ sw(t6, MemOperand(t5, JSObject::kElementsOffset)); | |
599 STATIC_ASSERT(3 * kPointerSize == JSObject::kHeaderSize); | |
600 __ Addu(t5, t5, Operand(3 * kPointerSize)); | |
601 | |
602 // Add the object tag to make the JSObject real, so that we can continue | |
603 // and jump into the continuation code at any time from now on. | |
604 __ Addu(t4, t4, Operand(kHeapObjectTag)); | |
605 | |
606 // Fill all the in-object properties with appropriate filler. | |
607 // t4: JSObject (tagged) | |
608 // t5: First in-object property of JSObject (not tagged) | |
609 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); | |
610 | |
611 if (!is_api_function) { | |
612 Label no_inobject_slack_tracking; | |
613 | |
614 MemOperand bit_field3 = FieldMemOperand(a2, Map::kBitField3Offset); | |
615 // Check if slack tracking is enabled. | |
616 __ lw(t0, bit_field3); | |
617 __ DecodeField<Map::ConstructionCounter>(t2, t0); | |
618 // t2: slack tracking counter | |
619 __ Branch(&no_inobject_slack_tracking, lt, t2, | |
620 Operand(Map::kSlackTrackingCounterEnd)); | |
621 // Decrease generous allocation count. | |
622 __ Subu(t0, t0, Operand(1 << Map::ConstructionCounter::kShift)); | |
623 __ sw(t0, bit_field3); | |
624 | |
625 // Allocate object with a slack. | |
626 __ lbu(a0, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset)); | |
627 __ sll(a0, a0, kPointerSizeLog2); | |
628 __ subu(a0, t3, a0); | |
629 // a0: offset of first field after pre-allocated fields | |
630 if (FLAG_debug_code) { | |
631 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields, t5, | |
632 Operand(a0)); | |
633 } | |
634 __ InitializeFieldsWithFiller(t5, a0, t7); | |
635 | |
636 // To allow truncation fill the remaining fields with one pointer | |
637 // filler map. | |
638 __ LoadRoot(t7, Heap::kOnePointerFillerMapRootIndex); | |
639 __ InitializeFieldsWithFiller(t5, t3, t7); | |
640 | |
641 // t2: slack tracking counter value before decreasing. | |
642 __ Branch(&allocated, ne, t2, Operand(Map::kSlackTrackingCounterEnd)); | |
643 | |
644 // Push the constructor, new_target and the object to the stack, | |
645 // and then the initial map as an argument to the runtime call. | |
646 __ Push(a1, a3, t4, a2); | |
647 __ CallRuntime(Runtime::kFinalizeInstanceSize); | |
648 __ Pop(a1, a3, t4); | |
649 | |
650 // Continue with JSObject being successfully allocated. | |
651 // a1: constructor function | |
652 // a3: new target | |
653 // t4: JSObject | |
654 __ jmp(&allocated); | |
655 | |
656 __ bind(&no_inobject_slack_tracking); | |
657 } | |
658 | |
659 __ InitializeFieldsWithFiller(t5, t3, t7); | |
660 | |
661 // Continue with JSObject being successfully allocated. | |
662 // a1: constructor function | |
663 // a3: new target | |
664 // t4: JSObject | |
665 __ jmp(&allocated); | |
666 } | |
667 | |
668 // Allocate the new receiver object using the runtime call. | |
669 // a1: constructor function | |
670 // a3: new target | |
671 __ bind(&rt_call); | |
672 | |
673 // Push the constructor and new_target twice, second pair as arguments | |
674 // to the runtime call. | |
675 __ Push(a1, a3, a1, a3); // constructor function, new target | |
676 __ CallRuntime(Runtime::kNewObject); | |
677 __ mov(t4, v0); | 553 __ mov(t4, v0); |
678 __ Pop(a1, a3); | 554 __ Pop(a1, a3); |
679 | 555 |
680 // Receiver for constructor call allocated. | 556 // ----------- S t a t e ------------- |
681 // a1: constructor function | 557 // -- a1: constructor function |
682 // a3: new target | 558 // -- a3: new target |
683 // t4: JSObject | 559 // -- t0: newly allocated object |
684 __ bind(&allocated); | 560 // ----------------------------------- |
685 | 561 |
686 // Retrieve smi-tagged arguments count from the stack. | 562 // Retrieve smi-tagged arguments count from the stack. |
687 __ lw(a0, MemOperand(sp)); | 563 __ lw(a0, MemOperand(sp)); |
688 } | 564 } |
689 | 565 |
690 __ SmiUntag(a0); | 566 __ SmiUntag(a0); |
691 | 567 |
692 if (create_implicit_receiver) { | 568 if (create_implicit_receiver) { |
693 // Push the allocated receiver to the stack. We need two copies | 569 // Push the allocated receiver to the stack. We need two copies |
694 // because we may have to return the original one and the calling | 570 // because we may have to return the original one and the calling |
(...skipping 2070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2765 } | 2641 } |
2766 } | 2642 } |
2767 | 2643 |
2768 | 2644 |
2769 #undef __ | 2645 #undef __ |
2770 | 2646 |
2771 } // namespace internal | 2647 } // namespace internal |
2772 } // namespace v8 | 2648 } // namespace v8 |
2773 | 2649 |
2774 #endif // V8_TARGET_ARCH_MIPS | 2650 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |