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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 5084 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5095 Label fast_elements_case; | 5095 Label fast_elements_case; |
5096 __ cmp(ecx, Immediate(FAST_ELEMENTS)); | 5096 __ cmp(ecx, Immediate(FAST_ELEMENTS)); |
5097 __ j(equal, &fast_elements_case); | 5097 __ j(equal, &fast_elements_case); |
5098 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 5098 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
5099 | 5099 |
5100 __ bind(&fast_elements_case); | 5100 __ bind(&fast_elements_case); |
5101 GenerateCase(masm, FAST_ELEMENTS); | 5101 GenerateCase(masm, FAST_ELEMENTS); |
5102 } | 5102 } |
5103 | 5103 |
5104 | 5104 |
5105 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { | |
5106 Register context_reg = esi; | |
Igor Sheludko
2015/07/18 20:52:43
Same comments as for x64.
Benedikt Meurer
2015/07/24 05:18:29
Acknowledged.
| |
5107 Register slot_reg = ebx; | |
5108 Register name_reg = ecx; | |
5109 Register result_reg = eax; | |
5110 Label slow_case; | |
5111 | |
5112 // Go up context chain to the script context. | |
5113 for (int i = 0; i < depth(); ++i) { | |
5114 __ mov(result_reg, ContextOperand(context_reg, Context::PREVIOUS_INDEX)); | |
5115 context_reg = result_reg; | |
5116 } | |
5117 | |
5118 // Load the PropertyCell value at the specified slot. | |
5119 __ mov(result_reg, ContextOperand(context_reg, slot_reg)); | |
5120 __ mov(result_reg, FieldOperand(result_reg, PropertyCell::kValueOffset)); | |
5121 | |
5122 // Check that value is not the_hole. | |
5123 __ CompareRoot(result_reg, Heap::kTheHoleValueRootIndex); | |
5124 __ j(equal, &slow_case, Label::kNear); | |
5125 __ Ret(); | |
5126 | |
5127 // Fallback to the runtime. | |
5128 __ bind(&slow_case); | |
5129 __ SmiTag(slot_reg); | |
5130 __ Pop(result_reg); | |
Igor Sheludko
2015/07/18 20:52:43
// Pop return address.
Benedikt Meurer
2015/07/24 05:18:29
Done.
| |
5131 __ Push(slot_reg); | |
5132 __ Push(name_reg); | |
5133 __ Push(result_reg); | |
5134 __ TailCallRuntime(Runtime::kLoadGlobalViaContext, 2, 1); | |
5135 } | |
5136 | |
5137 | |
5138 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { | |
5139 Register context_reg = esi; | |
5140 Register slot_reg = ebx; | |
5141 Register name_reg = ecx; | |
5142 Register value_reg = eax; | |
5143 Register cell_reg = edi; | |
5144 Register cell_details_reg = edx; | |
5145 Label fast_case, slow_case; | |
5146 | |
5147 if (FLAG_debug_code) { | |
5148 __ CompareRoot(value_reg, Heap::kTheHoleValueRootIndex); | |
5149 __ Check(not_equal, kUnexpectedValue); | |
5150 __ AssertName(name_reg); | |
5151 } | |
5152 | |
5153 // Go up context chain to the script context. | |
5154 for (int i = 0; i < depth(); ++i) { | |
5155 __ mov(cell_reg, ContextOperand(context_reg, Context::PREVIOUS_INDEX)); | |
5156 context_reg = cell_reg; | |
5157 } | |
5158 | |
5159 // Load the PropertyCell at the specified slot. | |
5160 __ mov(cell_reg, ContextOperand(context_reg, slot_reg)); | |
5161 | |
5162 // Load PropertyDetails for the cell (actually only the cell_type and kind). | |
5163 __ mov(cell_details_reg, | |
5164 FieldOperand(cell_reg, PropertyCell::kDetailsOffset)); | |
5165 __ SmiUntag(cell_details_reg); | |
5166 __ and_(cell_details_reg, | |
5167 Immediate(PropertyDetails::PropertyCellTypeField::kMask | | |
5168 PropertyDetails::KindField::kMask)); | |
5169 | |
5170 | |
5171 // Check if PropertyCell holds mutable data. | |
5172 Label not_mutable_data; | |
5173 __ cmp(cell_details_reg, | |
5174 Immediate(PropertyDetails::PropertyCellTypeField::encode( | |
5175 PropertyCellType::kMutable) | | |
5176 PropertyDetails::KindField::encode(kData))); | |
5177 __ j(not_equal, ¬_mutable_data); | |
5178 __ bind(&fast_case); | |
5179 __ mov(FieldOperand(cell_reg, PropertyCell::kValueOffset), value_reg); | |
5180 __ RecordWriteField(cell_reg, PropertyCell::kValueOffset, value_reg, | |
5181 cell_details_reg, kDontSaveFPRegs); | |
5182 // RecordWriteField clobbers the value register, so we need to reload. | |
5183 __ mov(value_reg, FieldOperand(cell_reg, PropertyCell::kValueOffset)); | |
5184 __ Ret(); | |
5185 __ bind(¬_mutable_data); | |
5186 | |
5187 // Check if PropertyCell value matches the new value (relevant for Constant | |
5188 // and ConstantType cells). | |
5189 Label not_same_value; | |
5190 __ cmp(value_reg, FieldOperand(cell_reg, PropertyCell::kValueOffset)); | |
5191 __ j(not_equal, ¬_same_value, | |
5192 FLAG_debug_code ? Label::kFar : Label::kNear); | |
5193 if (FLAG_debug_code) { | |
5194 Label done; | |
5195 // This can only be true for Constant and ConstantType cells, because we | |
5196 // never store the_hole via this stub. | |
5197 __ cmp(cell_details_reg, | |
5198 Immediate(PropertyDetails::PropertyCellTypeField::encode( | |
5199 PropertyCellType::kConstant) | | |
5200 PropertyDetails::KindField::encode(kData))); | |
5201 __ j(equal, &done); | |
5202 __ cmp(cell_details_reg, | |
5203 Immediate(PropertyDetails::PropertyCellTypeField::encode( | |
5204 PropertyCellType::kConstantType) | | |
5205 PropertyDetails::KindField::encode(kData))); | |
5206 __ Check(equal, kUnexpectedValue); | |
5207 __ bind(&done); | |
5208 } | |
5209 __ Ret(); | |
5210 __ bind(¬_same_value); | |
5211 | |
5212 // Check if PropertyCell contains data with constant type. | |
5213 __ cmp(cell_details_reg, | |
5214 Immediate(PropertyDetails::PropertyCellTypeField::encode( | |
5215 PropertyCellType::kConstantType) | | |
5216 PropertyDetails::KindField::encode(kData))); | |
5217 __ j(not_equal, &slow_case, Label::kNear); | |
5218 | |
5219 // Now either both old and new values must be SMIs or both must be heap | |
5220 // objects with same map. | |
5221 Label value_is_heap_object; | |
5222 Register cell_value_reg = cell_details_reg; | |
5223 __ mov(cell_value_reg, FieldOperand(cell_reg, PropertyCell::kValueOffset)); | |
5224 __ JumpIfNotSmi(value_reg, &value_is_heap_object, Label::kNear); | |
5225 __ JumpIfNotSmi(cell_value_reg, &slow_case, Label::kNear); | |
5226 // Old and new values are SMIs, no need for a write barrier here. | |
5227 __ mov(FieldOperand(cell_reg, PropertyCell::kValueOffset), value_reg); | |
5228 __ Ret(); | |
5229 __ bind(&value_is_heap_object); | |
5230 __ JumpIfSmi(cell_value_reg, &slow_case, Label::kNear); | |
5231 Register cell_value_map_reg = cell_value_reg; | |
5232 __ mov(cell_value_map_reg, | |
5233 FieldOperand(cell_value_reg, HeapObject::kMapOffset)); | |
5234 __ cmp(cell_value_map_reg, FieldOperand(value_reg, HeapObject::kMapOffset)); | |
5235 __ j(equal, &fast_case); | |
5236 | |
5237 // Fallback to the runtime. | |
5238 __ bind(&slow_case); | |
5239 __ SmiTag(slot_reg); | |
5240 __ Pop(cell_reg); | |
Igor Sheludko
2015/07/18 20:52:43
// Pop return address.
Benedikt Meurer
2015/07/24 05:18:29
Done.
| |
5241 __ Push(slot_reg); | |
5242 __ Push(name_reg); | |
5243 __ Push(value_reg); | |
5244 __ Push(cell_reg); | |
5245 __ TailCallRuntime(is_strict(language_mode()) | |
5246 ? Runtime::kStoreGlobalViaContext_Strict | |
5247 : Runtime::kStoreGlobalViaContext_Sloppy, | |
5248 3, 1); | |
5249 } | |
5250 | |
5251 | |
5105 // Generates an Operand for saving parameters after PrepareCallApiFunction. | 5252 // Generates an Operand for saving parameters after PrepareCallApiFunction. |
5106 static Operand ApiParameterOperand(int index) { | 5253 static Operand ApiParameterOperand(int index) { |
5107 return Operand(esp, index * kPointerSize); | 5254 return Operand(esp, index * kPointerSize); |
5108 } | 5255 } |
5109 | 5256 |
5110 | 5257 |
5111 // Prepares stack to put arguments (aligns and so on). Reserves | 5258 // Prepares stack to put arguments (aligns and so on). Reserves |
5112 // space for return value if needed (assumes the return value is a handle). | 5259 // space for return value if needed (assumes the return value is a handle). |
5113 // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1) | 5260 // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1) |
5114 // etc. Saves context (esi). If space was reserved for return value then | 5261 // etc. Saves context (esi). If space was reserved for return value then |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5485 Operand(ebp, 7 * kPointerSize), NULL); | 5632 Operand(ebp, 7 * kPointerSize), NULL); |
5486 } | 5633 } |
5487 | 5634 |
5488 | 5635 |
5489 #undef __ | 5636 #undef __ |
5490 | 5637 |
5491 } // namespace internal | 5638 } // namespace internal |
5492 } // namespace v8 | 5639 } // namespace v8 |
5493 | 5640 |
5494 #endif // V8_TARGET_ARCH_IA32 | 5641 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |