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_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 4563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4574 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 4574 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
4575 __ Push(Operand(edx, StandardFrameConstants::kFunctionOffset)); | 4575 __ Push(Operand(edx, StandardFrameConstants::kFunctionOffset)); |
4576 } else { | 4576 } else { |
4577 __ Push(Operand(ebp, StandardFrameConstants::kFunctionOffset)); | 4577 __ Push(Operand(ebp, StandardFrameConstants::kFunctionOffset)); |
4578 } | 4578 } |
4579 __ PushReturnAddressFrom(ecx); | 4579 __ PushReturnAddressFrom(ecx); |
4580 __ TailCallRuntime(Runtime::kNewStrictArguments); | 4580 __ TailCallRuntime(Runtime::kNewStrictArguments); |
4581 } | 4581 } |
4582 | 4582 |
4583 | 4583 |
4584 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { | |
4585 Register context_reg = esi; | |
4586 Register slot_reg = ebx; | |
4587 Register value_reg = eax; | |
4588 Register cell_reg = edi; | |
4589 Register cell_details_reg = edx; | |
4590 Register cell_value_reg = ecx; | |
4591 Label fast_heapobject_case, fast_smi_case, slow_case; | |
4592 | |
4593 if (FLAG_debug_code) { | |
4594 __ CompareRoot(value_reg, Heap::kTheHoleValueRootIndex); | |
4595 __ Check(not_equal, kUnexpectedValue); | |
4596 } | |
4597 | |
4598 // Go up context chain to the script context. | |
4599 for (int i = 0; i < depth(); ++i) { | |
4600 __ mov(cell_reg, ContextOperand(context_reg, Context::PREVIOUS_INDEX)); | |
4601 context_reg = cell_reg; | |
4602 } | |
4603 | |
4604 // Load the PropertyCell at the specified slot. | |
4605 __ mov(cell_reg, ContextOperand(context_reg, slot_reg)); | |
4606 | |
4607 // Load PropertyDetails for the cell (actually only the cell_type and kind). | |
4608 __ mov(cell_details_reg, | |
4609 FieldOperand(cell_reg, PropertyCell::kDetailsOffset)); | |
4610 __ SmiUntag(cell_details_reg); | |
4611 __ and_(cell_details_reg, | |
4612 Immediate(PropertyDetails::PropertyCellTypeField::kMask | | |
4613 PropertyDetails::KindField::kMask | | |
4614 PropertyDetails::kAttributesReadOnlyMask)); | |
4615 | |
4616 // Check if PropertyCell holds mutable data. | |
4617 Label not_mutable_data; | |
4618 __ cmp(cell_details_reg, | |
4619 Immediate(PropertyDetails::PropertyCellTypeField::encode( | |
4620 PropertyCellType::kMutable) | | |
4621 PropertyDetails::KindField::encode(kData))); | |
4622 __ j(not_equal, ¬_mutable_data); | |
4623 __ JumpIfSmi(value_reg, &fast_smi_case); | |
4624 __ bind(&fast_heapobject_case); | |
4625 __ mov(FieldOperand(cell_reg, PropertyCell::kValueOffset), value_reg); | |
4626 __ RecordWriteField(cell_reg, PropertyCell::kValueOffset, value_reg, | |
4627 cell_details_reg, kDontSaveFPRegs, EMIT_REMEMBERED_SET, | |
4628 OMIT_SMI_CHECK); | |
4629 // RecordWriteField clobbers the value register, so we need to reload. | |
4630 __ mov(value_reg, FieldOperand(cell_reg, PropertyCell::kValueOffset)); | |
4631 __ Ret(); | |
4632 __ bind(¬_mutable_data); | |
4633 | |
4634 // Check if PropertyCell value matches the new value (relevant for Constant, | |
4635 // ConstantType and Undefined cells). | |
4636 Label not_same_value; | |
4637 __ mov(cell_value_reg, FieldOperand(cell_reg, PropertyCell::kValueOffset)); | |
4638 __ cmp(cell_value_reg, value_reg); | |
4639 __ j(not_equal, ¬_same_value, | |
4640 FLAG_debug_code ? Label::kFar : Label::kNear); | |
4641 // Make sure the PropertyCell is not marked READ_ONLY. | |
4642 __ test(cell_details_reg, | |
4643 Immediate(PropertyDetails::kAttributesReadOnlyMask)); | |
4644 __ j(not_zero, &slow_case); | |
4645 if (FLAG_debug_code) { | |
4646 Label done; | |
4647 // This can only be true for Constant, ConstantType and Undefined cells, | |
4648 // because we never store the_hole via this stub. | |
4649 __ cmp(cell_details_reg, | |
4650 Immediate(PropertyDetails::PropertyCellTypeField::encode( | |
4651 PropertyCellType::kConstant) | | |
4652 PropertyDetails::KindField::encode(kData))); | |
4653 __ j(equal, &done); | |
4654 __ cmp(cell_details_reg, | |
4655 Immediate(PropertyDetails::PropertyCellTypeField::encode( | |
4656 PropertyCellType::kConstantType) | | |
4657 PropertyDetails::KindField::encode(kData))); | |
4658 __ j(equal, &done); | |
4659 __ cmp(cell_details_reg, | |
4660 Immediate(PropertyDetails::PropertyCellTypeField::encode( | |
4661 PropertyCellType::kUndefined) | | |
4662 PropertyDetails::KindField::encode(kData))); | |
4663 __ Check(equal, kUnexpectedValue); | |
4664 __ bind(&done); | |
4665 } | |
4666 __ Ret(); | |
4667 __ bind(¬_same_value); | |
4668 | |
4669 // Check if PropertyCell contains data with constant type (and is not | |
4670 // READ_ONLY). | |
4671 __ cmp(cell_details_reg, | |
4672 Immediate(PropertyDetails::PropertyCellTypeField::encode( | |
4673 PropertyCellType::kConstantType) | | |
4674 PropertyDetails::KindField::encode(kData))); | |
4675 __ j(not_equal, &slow_case, Label::kNear); | |
4676 | |
4677 // Now either both old and new values must be SMIs or both must be heap | |
4678 // objects with same map. | |
4679 Label value_is_heap_object; | |
4680 __ JumpIfNotSmi(value_reg, &value_is_heap_object, Label::kNear); | |
4681 __ JumpIfNotSmi(cell_value_reg, &slow_case, Label::kNear); | |
4682 // Old and new values are SMIs, no need for a write barrier here. | |
4683 __ bind(&fast_smi_case); | |
4684 __ mov(FieldOperand(cell_reg, PropertyCell::kValueOffset), value_reg); | |
4685 __ Ret(); | |
4686 __ bind(&value_is_heap_object); | |
4687 __ JumpIfSmi(cell_value_reg, &slow_case, Label::kNear); | |
4688 Register cell_value_map_reg = cell_value_reg; | |
4689 __ mov(cell_value_map_reg, | |
4690 FieldOperand(cell_value_reg, HeapObject::kMapOffset)); | |
4691 __ cmp(cell_value_map_reg, FieldOperand(value_reg, HeapObject::kMapOffset)); | |
4692 __ j(equal, &fast_heapobject_case); | |
4693 | |
4694 // Fallback to the runtime. | |
4695 __ bind(&slow_case); | |
4696 __ SmiTag(slot_reg); | |
4697 __ Pop(cell_reg); // Pop return address. | |
4698 __ Push(slot_reg); | |
4699 __ Push(value_reg); | |
4700 __ Push(cell_reg); // Push return address. | |
4701 __ TailCallRuntime(is_strict(language_mode()) | |
4702 ? Runtime::kStoreGlobalViaContext_Strict | |
4703 : Runtime::kStoreGlobalViaContext_Sloppy); | |
4704 } | |
4705 | |
4706 | |
4707 // Generates an Operand for saving parameters after PrepareCallApiFunction. | 4584 // Generates an Operand for saving parameters after PrepareCallApiFunction. |
4708 static Operand ApiParameterOperand(int index) { | 4585 static Operand ApiParameterOperand(int index) { |
4709 return Operand(esp, index * kPointerSize); | 4586 return Operand(esp, index * kPointerSize); |
4710 } | 4587 } |
4711 | 4588 |
4712 | 4589 |
4713 // Prepares stack to put arguments (aligns and so on). Reserves | 4590 // Prepares stack to put arguments (aligns and so on). Reserves |
4714 // space for return value if needed (assumes the return value is a handle). | 4591 // space for return value if needed (assumes the return value is a handle). |
4715 // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1) | 4592 // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1) |
4716 // etc. Saves context (esi). If space was reserved for return value then | 4593 // etc. Saves context (esi). If space was reserved for return value then |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5081 kStackUnwindSpace, nullptr, return_value_operand, | 4958 kStackUnwindSpace, nullptr, return_value_operand, |
5082 NULL); | 4959 NULL); |
5083 } | 4960 } |
5084 | 4961 |
5085 #undef __ | 4962 #undef __ |
5086 | 4963 |
5087 } // namespace internal | 4964 } // namespace internal |
5088 } // namespace v8 | 4965 } // namespace v8 |
5089 | 4966 |
5090 #endif // V8_TARGET_ARCH_IA32 | 4967 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |