| 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 |