Chromium Code Reviews| 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 |