OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 5015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5026 Label fast_elements_case; | 5026 Label fast_elements_case; |
5027 __ cmpl(rcx, Immediate(FAST_ELEMENTS)); | 5027 __ cmpl(rcx, Immediate(FAST_ELEMENTS)); |
5028 __ j(equal, &fast_elements_case); | 5028 __ j(equal, &fast_elements_case); |
5029 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 5029 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
5030 | 5030 |
5031 __ bind(&fast_elements_case); | 5031 __ bind(&fast_elements_case); |
5032 GenerateCase(masm, FAST_ELEMENTS); | 5032 GenerateCase(masm, FAST_ELEMENTS); |
5033 } | 5033 } |
5034 | 5034 |
5035 | 5035 |
| 5036 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { |
| 5037 Register context_reg = rsi; |
| 5038 Register slot_reg = rbx; |
| 5039 Register name_reg = rcx; |
| 5040 Register result_reg = rax; |
| 5041 Label slow_case; |
| 5042 |
| 5043 // Go up context chain to the script context. |
| 5044 for (int i = 0; i < depth(); ++i) { |
| 5045 __ movp(rdi, ContextOperand(context_reg, Context::PREVIOUS_INDEX)); |
| 5046 context_reg = rdi; |
| 5047 } |
| 5048 |
| 5049 // Load the PropertyCell value at the specified slot. |
| 5050 __ movp(result_reg, ContextOperand(context_reg, slot_reg)); |
| 5051 __ movp(result_reg, FieldOperand(result_reg, PropertyCell::kValueOffset)); |
| 5052 |
| 5053 // Check that value is not the_hole. |
| 5054 __ CompareRoot(result_reg, Heap::kTheHoleValueRootIndex); |
| 5055 __ j(equal, &slow_case, Label::kNear); |
| 5056 __ Ret(); |
| 5057 |
| 5058 // Fallback to the runtime. |
| 5059 __ bind(&slow_case); |
| 5060 __ Integer32ToSmi(slot_reg, slot_reg); |
| 5061 __ PopReturnAddressTo(kScratchRegister); |
| 5062 __ Push(slot_reg); |
| 5063 __ Push(name_reg); |
| 5064 __ Push(kScratchRegister); |
| 5065 __ TailCallRuntime(Runtime::kLoadGlobalViaContext, 2, 1); |
| 5066 } |
| 5067 |
| 5068 |
| 5069 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { |
| 5070 Register context_reg = rsi; |
| 5071 Register slot_reg = rbx; |
| 5072 Register name_reg = rcx; |
| 5073 Register value_reg = rax; |
| 5074 Register cell_reg = r8; |
| 5075 Register cell_details_reg = rdx; |
| 5076 Register cell_value_reg = r9; |
| 5077 Label fast_heapobject_case, fast_smi_case, slow_case; |
| 5078 |
| 5079 if (FLAG_debug_code) { |
| 5080 __ CompareRoot(value_reg, Heap::kTheHoleValueRootIndex); |
| 5081 __ Check(not_equal, kUnexpectedValue); |
| 5082 __ AssertName(name_reg); |
| 5083 } |
| 5084 |
| 5085 // Go up context chain to the script context. |
| 5086 for (int i = 0; i < depth(); ++i) { |
| 5087 __ movp(rdi, ContextOperand(context_reg, Context::PREVIOUS_INDEX)); |
| 5088 context_reg = rdi; |
| 5089 } |
| 5090 |
| 5091 // Load the PropertyCell at the specified slot. |
| 5092 __ movp(cell_reg, ContextOperand(context_reg, slot_reg)); |
| 5093 |
| 5094 // Load PropertyDetails for the cell (actually only the cell_type and kind). |
| 5095 __ SmiToInteger32(cell_details_reg, |
| 5096 FieldOperand(cell_reg, PropertyCell::kDetailsOffset)); |
| 5097 __ andl(cell_details_reg, |
| 5098 Immediate(PropertyDetails::PropertyCellTypeField::kMask | |
| 5099 PropertyDetails::KindField::kMask)); |
| 5100 |
| 5101 |
| 5102 // Check if PropertyCell holds mutable data. |
| 5103 Label not_mutable_data; |
| 5104 __ cmpl(cell_details_reg, |
| 5105 Immediate(PropertyDetails::PropertyCellTypeField::encode( |
| 5106 PropertyCellType::kMutable) | |
| 5107 PropertyDetails::KindField::encode(kData))); |
| 5108 __ j(not_equal, ¬_mutable_data); |
| 5109 __ JumpIfSmi(value_reg, &fast_smi_case); |
| 5110 __ bind(&fast_heapobject_case); |
| 5111 __ movp(FieldOperand(cell_reg, PropertyCell::kValueOffset), value_reg); |
| 5112 __ RecordWriteField(cell_reg, PropertyCell::kValueOffset, value_reg, |
| 5113 cell_value_reg, kDontSaveFPRegs, EMIT_REMEMBERED_SET, |
| 5114 OMIT_SMI_CHECK); |
| 5115 // RecordWriteField clobbers the value register, so we need to reload. |
| 5116 __ movp(value_reg, FieldOperand(cell_reg, PropertyCell::kValueOffset)); |
| 5117 __ Ret(); |
| 5118 __ bind(¬_mutable_data); |
| 5119 |
| 5120 // Check if PropertyCell value matches the new value (relevant for Constant, |
| 5121 // ConstantType and Undefined cells). |
| 5122 Label not_same_value; |
| 5123 __ movp(cell_value_reg, FieldOperand(cell_reg, PropertyCell::kValueOffset)); |
| 5124 __ cmpp(cell_value_reg, value_reg); |
| 5125 __ j(not_equal, ¬_same_value, |
| 5126 FLAG_debug_code ? Label::kFar : Label::kNear); |
| 5127 if (FLAG_debug_code) { |
| 5128 Label done; |
| 5129 // This can only be true for Constant, ConstantType and Undefined cells, |
| 5130 // because we never store the_hole via this stub. |
| 5131 __ cmpl(cell_details_reg, |
| 5132 Immediate(PropertyDetails::PropertyCellTypeField::encode( |
| 5133 PropertyCellType::kConstant) | |
| 5134 PropertyDetails::KindField::encode(kData))); |
| 5135 __ j(equal, &done); |
| 5136 __ cmpl(cell_details_reg, |
| 5137 Immediate(PropertyDetails::PropertyCellTypeField::encode( |
| 5138 PropertyCellType::kConstantType) | |
| 5139 PropertyDetails::KindField::encode(kData))); |
| 5140 __ j(equal, &done); |
| 5141 __ cmpl(cell_details_reg, |
| 5142 Immediate(PropertyDetails::PropertyCellTypeField::encode( |
| 5143 PropertyCellType::kUndefined) | |
| 5144 PropertyDetails::KindField::encode(kData))); |
| 5145 __ Check(equal, kUnexpectedValue); |
| 5146 __ bind(&done); |
| 5147 } |
| 5148 __ Ret(); |
| 5149 __ bind(¬_same_value); |
| 5150 |
| 5151 // Check if PropertyCell contains data with constant type. |
| 5152 __ cmpl(cell_details_reg, |
| 5153 Immediate(PropertyDetails::PropertyCellTypeField::encode( |
| 5154 PropertyCellType::kConstantType) | |
| 5155 PropertyDetails::KindField::encode(kData))); |
| 5156 __ j(not_equal, &slow_case, Label::kNear); |
| 5157 |
| 5158 // Now either both old and new values must be SMIs or both must be heap |
| 5159 // objects with same map. |
| 5160 Label value_is_heap_object; |
| 5161 __ JumpIfNotSmi(value_reg, &value_is_heap_object, Label::kNear); |
| 5162 __ JumpIfNotSmi(cell_value_reg, &slow_case, Label::kNear); |
| 5163 // Old and new values are SMIs, no need for a write barrier here. |
| 5164 __ bind(&fast_smi_case); |
| 5165 __ movp(FieldOperand(cell_reg, PropertyCell::kValueOffset), value_reg); |
| 5166 __ Ret(); |
| 5167 __ bind(&value_is_heap_object); |
| 5168 __ JumpIfSmi(cell_value_reg, &slow_case, Label::kNear); |
| 5169 Register cell_value_map_reg = cell_value_reg; |
| 5170 __ movp(cell_value_map_reg, |
| 5171 FieldOperand(cell_value_reg, HeapObject::kMapOffset)); |
| 5172 __ cmpp(cell_value_map_reg, FieldOperand(value_reg, HeapObject::kMapOffset)); |
| 5173 __ j(equal, &fast_heapobject_case); |
| 5174 |
| 5175 // Fallback to the runtime. |
| 5176 __ bind(&slow_case); |
| 5177 __ Integer32ToSmi(slot_reg, slot_reg); |
| 5178 __ PopReturnAddressTo(kScratchRegister); |
| 5179 __ Push(slot_reg); |
| 5180 __ Push(name_reg); |
| 5181 __ Push(value_reg); |
| 5182 __ Push(kScratchRegister); |
| 5183 __ TailCallRuntime(is_strict(language_mode()) |
| 5184 ? Runtime::kStoreGlobalViaContext_Strict |
| 5185 : Runtime::kStoreGlobalViaContext_Sloppy, |
| 5186 3, 1); |
| 5187 } |
| 5188 |
| 5189 |
5036 static int Offset(ExternalReference ref0, ExternalReference ref1) { | 5190 static int Offset(ExternalReference ref0, ExternalReference ref1) { |
5037 int64_t offset = (ref0.address() - ref1.address()); | 5191 int64_t offset = (ref0.address() - ref1.address()); |
5038 // Check that fits into int. | 5192 // Check that fits into int. |
5039 DCHECK(static_cast<int>(offset) == offset); | 5193 DCHECK(static_cast<int>(offset) == offset); |
5040 return static_cast<int>(offset); | 5194 return static_cast<int>(offset); |
5041 } | 5195 } |
5042 | 5196 |
5043 | 5197 |
5044 // Prepares stack to put arguments (aligns and so on). WIN64 calling | 5198 // Prepares stack to put arguments (aligns and so on). WIN64 calling |
5045 // convention requires to put the pointer to the return value slot into | 5199 // convention requires to put the pointer to the return value slot into |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5428 kStackSpace, nullptr, return_value_operand, NULL); | 5582 kStackSpace, nullptr, return_value_operand, NULL); |
5429 } | 5583 } |
5430 | 5584 |
5431 | 5585 |
5432 #undef __ | 5586 #undef __ |
5433 | 5587 |
5434 } // namespace internal | 5588 } // namespace internal |
5435 } // namespace v8 | 5589 } // namespace v8 |
5436 | 5590 |
5437 #endif // V8_TARGET_ARCH_X64 | 5591 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |