OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 GenerateDeferredCode() && | 95 GenerateDeferredCode() && |
96 GenerateJumpTable() && | 96 GenerateJumpTable() && |
97 GenerateSafepointTable(); | 97 GenerateSafepointTable(); |
98 } | 98 } |
99 | 99 |
100 | 100 |
101 void LCodeGen::FinishCode(Handle<Code> code) { | 101 void LCodeGen::FinishCode(Handle<Code> code) { |
102 ASSERT(is_done()); | 102 ASSERT(is_done()); |
103 code->set_stack_slots(GetStackSlotCount()); | 103 code->set_stack_slots(GetStackSlotCount()); |
104 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 104 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
105 if (FLAG_weak_embedded_maps_in_optimized_code) { | 105 if (FLAG_weak_embedded_maps_in_optimized_code && |
| 106 code->kind() == Code::OPTIMIZED_FUNCTION) { |
106 RegisterDependentCodeForEmbeddedMaps(code); | 107 RegisterDependentCodeForEmbeddedMaps(code); |
107 } | 108 } |
108 PopulateDeoptimizationData(code); | 109 PopulateDeoptimizationData(code); |
109 if (!info()->IsStub()) { | 110 if (!info()->IsStub()) { |
110 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); | 111 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); |
111 } | 112 } |
112 for (int i = 0 ; i < prototype_maps_.length(); i++) { | 113 for (int i = 0 ; i < prototype_maps_.length(); i++) { |
113 prototype_maps_.at(i)->AddDependentCode( | 114 prototype_maps_.at(i)->AddDependentCode( |
114 DependentCode::kPrototypeCheckGroup, code); | 115 DependentCode::kPrototypeCheckGroup, code); |
115 } | 116 } |
(...skipping 2661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2777 int parameter_count = ToInteger32(instr->constant_parameter_count()); | 2778 int parameter_count = ToInteger32(instr->constant_parameter_count()); |
2778 if (dynamic_frame_alignment && FLAG_debug_code) { | 2779 if (dynamic_frame_alignment && FLAG_debug_code) { |
2779 __ cmp(Operand(esp, | 2780 __ cmp(Operand(esp, |
2780 (parameter_count + extra_value_count) * kPointerSize), | 2781 (parameter_count + extra_value_count) * kPointerSize), |
2781 Immediate(kAlignmentZapValue)); | 2782 Immediate(kAlignmentZapValue)); |
2782 __ Assert(equal, "expected alignment marker"); | 2783 __ Assert(equal, "expected alignment marker"); |
2783 } | 2784 } |
2784 __ Ret((parameter_count + extra_value_count) * kPointerSize, ecx); | 2785 __ Ret((parameter_count + extra_value_count) * kPointerSize, ecx); |
2785 } else { | 2786 } else { |
2786 Register reg = ToRegister(instr->parameter_count()); | 2787 Register reg = ToRegister(instr->parameter_count()); |
| 2788 __ SmiUntag(reg); // it is a smi |
2787 Register return_addr_reg = reg.is(ecx) ? ebx : ecx; | 2789 Register return_addr_reg = reg.is(ecx) ? ebx : ecx; |
2788 if (dynamic_frame_alignment && FLAG_debug_code) { | 2790 if (dynamic_frame_alignment && FLAG_debug_code) { |
2789 ASSERT(extra_value_count == 2); | 2791 ASSERT(extra_value_count == 2); |
2790 __ cmp(Operand(esp, reg, times_pointer_size, | 2792 __ cmp(Operand(esp, reg, times_pointer_size, |
2791 extra_value_count * kPointerSize), | 2793 extra_value_count * kPointerSize), |
2792 Immediate(kAlignmentZapValue)); | 2794 Immediate(kAlignmentZapValue)); |
2793 __ Assert(equal, "expected alignment marker"); | 2795 __ Assert(equal, "expected alignment marker"); |
2794 } | 2796 } |
2795 | 2797 |
2796 // emit code to restore stack based on instr->parameter_count() | 2798 // emit code to restore stack based on instr->parameter_count() |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3189 LLoadExternalArrayPointer* instr) { | 3191 LLoadExternalArrayPointer* instr) { |
3190 Register result = ToRegister(instr->result()); | 3192 Register result = ToRegister(instr->result()); |
3191 Register input = ToRegister(instr->object()); | 3193 Register input = ToRegister(instr->object()); |
3192 __ mov(result, FieldOperand(input, | 3194 __ mov(result, FieldOperand(input, |
3193 ExternalArray::kExternalPointerOffset)); | 3195 ExternalArray::kExternalPointerOffset)); |
3194 } | 3196 } |
3195 | 3197 |
3196 | 3198 |
3197 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 3199 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
3198 Register arguments = ToRegister(instr->arguments()); | 3200 Register arguments = ToRegister(instr->arguments()); |
3199 Register length = ToRegister(instr->length()); | |
3200 Operand index = ToOperand(instr->index()); | |
3201 Register result = ToRegister(instr->result()); | 3201 Register result = ToRegister(instr->result()); |
3202 // There are two words between the frame pointer and the last argument. | 3202 if (instr->length()->IsConstantOperand() && |
3203 // Subtracting from length accounts for one of them add one more. | 3203 instr->index()->IsConstantOperand()) { |
3204 __ sub(length, index); | 3204 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
3205 __ mov(result, Operand(arguments, length, times_4, kPointerSize)); | 3205 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); |
| 3206 int index = (const_length - const_index) + 1; |
| 3207 __ mov(result, Operand(arguments, index * kPointerSize)); |
| 3208 } else { |
| 3209 Register length = ToRegister(instr->length()); |
| 3210 Operand index = ToOperand(instr->index()); |
| 3211 // There are two words between the frame pointer and the last argument. |
| 3212 // Subtracting from length accounts for one of them add one more. |
| 3213 __ sub(length, index); |
| 3214 __ mov(result, Operand(arguments, length, times_4, kPointerSize)); |
| 3215 } |
3206 } | 3216 } |
3207 | 3217 |
3208 | 3218 |
3209 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { | 3219 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
3210 ElementsKind elements_kind = instr->elements_kind(); | 3220 ElementsKind elements_kind = instr->elements_kind(); |
3211 LOperand* key = instr->key(); | 3221 LOperand* key = instr->key(); |
3212 if (!key->IsConstantOperand() && | 3222 if (!key->IsConstantOperand() && |
3213 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), | 3223 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), |
3214 elements_kind)) { | 3224 elements_kind)) { |
3215 __ SmiUntag(ToRegister(key)); | 3225 __ SmiUntag(ToRegister(key)); |
(...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4191 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4201 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
4192 } | 4202 } |
4193 | 4203 |
4194 | 4204 |
4195 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 4205 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
4196 ASSERT(ToRegister(instr->context()).is(esi)); | 4206 ASSERT(ToRegister(instr->context()).is(esi)); |
4197 ASSERT(ToRegister(instr->constructor()).is(edi)); | 4207 ASSERT(ToRegister(instr->constructor()).is(edi)); |
4198 ASSERT(ToRegister(instr->result()).is(eax)); | 4208 ASSERT(ToRegister(instr->result()).is(eax)); |
4199 ASSERT(FLAG_optimize_constructed_arrays); | 4209 ASSERT(FLAG_optimize_constructed_arrays); |
4200 | 4210 |
| 4211 __ Set(eax, Immediate(instr->arity())); |
4201 __ mov(ebx, instr->hydrogen()->property_cell()); | 4212 __ mov(ebx, instr->hydrogen()->property_cell()); |
4202 Handle<Code> array_construct_code = | 4213 Object* cell_value = instr->hydrogen()->property_cell()->value(); |
4203 isolate()->builtins()->ArrayConstructCode(); | 4214 ElementsKind kind = static_cast<ElementsKind>(Smi::cast(cell_value)->value()); |
4204 __ Set(eax, Immediate(instr->arity())); | 4215 if (instr->arity() == 0) { |
4205 CallCode(array_construct_code, RelocInfo::CONSTRUCT_CALL, instr); | 4216 ArrayNoArgumentConstructorStub stub(kind); |
| 4217 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4218 } else if (instr->arity() == 1) { |
| 4219 ArraySingleArgumentConstructorStub stub(kind); |
| 4220 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4221 } else { |
| 4222 ArrayNArgumentsConstructorStub stub(kind); |
| 4223 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4224 } |
4206 } | 4225 } |
4207 | 4226 |
4208 | 4227 |
4209 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 4228 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
4210 CallRuntime(instr->function(), instr->arity(), instr); | 4229 CallRuntime(instr->function(), instr->arity(), instr); |
4211 } | 4230 } |
4212 | 4231 |
4213 | 4232 |
4214 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { | 4233 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { |
4215 Register result = ToRegister(instr->result()); | 4234 Register result = ToRegister(instr->result()); |
4216 Register base = ToRegister(instr->base_object()); | 4235 Register base = ToRegister(instr->base_object()); |
4217 __ lea(result, Operand(base, instr->offset())); | 4236 __ lea(result, Operand(base, instr->offset())); |
4218 } | 4237 } |
4219 | 4238 |
4220 | 4239 |
4221 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 4240 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
4222 Register object = ToRegister(instr->object()); | 4241 Register object = ToRegister(instr->object()); |
4223 Register value = ToRegister(instr->value()); | |
4224 int offset = instr->offset(); | 4242 int offset = instr->offset(); |
4225 | 4243 |
4226 if (!instr->transition().is_null()) { | 4244 if (!instr->transition().is_null()) { |
4227 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { | 4245 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { |
4228 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); | 4246 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); |
4229 } else { | 4247 } else { |
4230 Register temp = ToRegister(instr->temp()); | 4248 Register temp = ToRegister(instr->temp()); |
4231 Register temp_map = ToRegister(instr->temp_map()); | 4249 Register temp_map = ToRegister(instr->temp_map()); |
4232 __ mov(temp_map, instr->transition()); | 4250 __ mov(temp_map, instr->transition()); |
4233 __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map); | 4251 __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map); |
4234 // Update the write barrier for the map field. | 4252 // Update the write barrier for the map field. |
4235 __ RecordWriteField(object, | 4253 __ RecordWriteField(object, |
4236 HeapObject::kMapOffset, | 4254 HeapObject::kMapOffset, |
4237 temp_map, | 4255 temp_map, |
4238 temp, | 4256 temp, |
4239 GetSaveFPRegsMode(), | 4257 GetSaveFPRegsMode(), |
4240 OMIT_REMEMBERED_SET, | 4258 OMIT_REMEMBERED_SET, |
4241 OMIT_SMI_CHECK); | 4259 OMIT_SMI_CHECK); |
4242 } | 4260 } |
4243 } | 4261 } |
4244 | 4262 |
4245 // Do the store. | 4263 // Do the store. |
4246 HType type = instr->hydrogen()->value()->type(); | 4264 HType type = instr->hydrogen()->value()->type(); |
4247 SmiCheck check_needed = | 4265 SmiCheck check_needed = |
4248 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 4266 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
4249 if (instr->is_in_object()) { | 4267 if (instr->is_in_object()) { |
4250 __ mov(FieldOperand(object, offset), value); | 4268 if (instr->value()->IsConstantOperand()) { |
| 4269 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4270 if (IsInteger32(operand_value)) { |
| 4271 int const_value = ToInteger32(operand_value); |
| 4272 __ mov(FieldOperand(object, offset), Immediate(const_value)); |
| 4273 } else { |
| 4274 if (operand_value->IsRegister()) { |
| 4275 __ mov(FieldOperand(object, offset), ToRegister(operand_value)); |
| 4276 } else { |
| 4277 Handle<Object> handle_value = ToHandle(operand_value); |
| 4278 __ mov(FieldOperand(object, offset), handle_value); |
| 4279 } |
| 4280 } |
| 4281 } else { |
| 4282 __ mov(FieldOperand(object, offset), ToRegister(instr->value())); |
| 4283 } |
| 4284 |
4251 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4285 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4286 Register value = ToRegister(instr->value()); |
4252 Register temp = ToRegister(instr->temp()); | 4287 Register temp = ToRegister(instr->temp()); |
4253 // Update the write barrier for the object for in-object properties. | 4288 // Update the write barrier for the object for in-object properties. |
4254 __ RecordWriteField(object, | 4289 __ RecordWriteField(object, |
4255 offset, | 4290 offset, |
4256 value, | 4291 value, |
4257 temp, | 4292 temp, |
4258 GetSaveFPRegsMode(), | 4293 GetSaveFPRegsMode(), |
4259 EMIT_REMEMBERED_SET, | 4294 EMIT_REMEMBERED_SET, |
4260 check_needed); | 4295 check_needed); |
4261 } | 4296 } |
4262 } else { | 4297 } else { |
4263 Register temp = ToRegister(instr->temp()); | 4298 Register temp = ToRegister(instr->temp()); |
4264 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); | 4299 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); |
4265 __ mov(FieldOperand(temp, offset), value); | 4300 |
| 4301 if (instr->value()->IsConstantOperand()) { |
| 4302 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4303 if (IsInteger32(operand_value)) { |
| 4304 int const_value = ToInteger32(operand_value); |
| 4305 __ mov(FieldOperand(temp, offset), Immediate(const_value)); |
| 4306 } else { |
| 4307 if (operand_value->IsRegister()) { |
| 4308 __ mov(FieldOperand(temp, offset), ToRegister(operand_value)); |
| 4309 } else { |
| 4310 Handle<Object> handle_value = ToHandle(operand_value); |
| 4311 __ mov(FieldOperand(temp, offset), handle_value); |
| 4312 } |
| 4313 } |
| 4314 } else { |
| 4315 __ mov(FieldOperand(temp, offset), ToRegister(instr->value())); |
| 4316 } |
| 4317 |
4266 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4318 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4319 Register value = ToRegister(instr->value()); |
4267 // Update the write barrier for the properties array. | 4320 // Update the write barrier for the properties array. |
4268 // object is used as a scratch register. | 4321 // object is used as a scratch register. |
4269 __ RecordWriteField(temp, | 4322 __ RecordWriteField(temp, |
4270 offset, | 4323 offset, |
4271 value, | 4324 value, |
4272 object, | 4325 object, |
4273 GetSaveFPRegsMode(), | 4326 GetSaveFPRegsMode(), |
4274 EMIT_REMEMBERED_SET, | 4327 EMIT_REMEMBERED_SET, |
4275 check_needed); | 4328 check_needed); |
4276 } | 4329 } |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4444 } | 4497 } |
4445 | 4498 |
4446 __ bind(&no_special_nan_handling); | 4499 __ bind(&no_special_nan_handling); |
4447 __ fst_d(double_store_operand); | 4500 __ fst_d(double_store_operand); |
4448 } | 4501 } |
4449 } | 4502 } |
4450 } | 4503 } |
4451 | 4504 |
4452 | 4505 |
4453 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { | 4506 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
4454 Register value = ToRegister(instr->value()); | |
4455 Register elements = ToRegister(instr->elements()); | 4507 Register elements = ToRegister(instr->elements()); |
4456 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; | 4508 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; |
4457 | 4509 |
4458 Operand operand = BuildFastArrayOperand( | 4510 Operand operand = BuildFastArrayOperand( |
4459 instr->elements(), | 4511 instr->elements(), |
4460 instr->key(), | 4512 instr->key(), |
4461 instr->hydrogen()->key()->representation(), | 4513 instr->hydrogen()->key()->representation(), |
4462 FAST_ELEMENTS, | 4514 FAST_ELEMENTS, |
4463 FixedArray::kHeaderSize - kHeapObjectTag, | 4515 FixedArray::kHeaderSize - kHeapObjectTag, |
4464 instr->additional_index()); | 4516 instr->additional_index()); |
4465 __ mov(operand, value); | 4517 if (instr->value()->IsRegister()) { |
| 4518 __ mov(operand, ToRegister(instr->value())); |
| 4519 } else { |
| 4520 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4521 if (IsInteger32(operand_value)) { |
| 4522 int const_value = ToInteger32(operand_value); |
| 4523 __ mov(operand, Immediate(const_value)); |
| 4524 } else { |
| 4525 Handle<Object> handle_value = ToHandle(operand_value); |
| 4526 __ mov(operand, handle_value); |
| 4527 } |
| 4528 } |
4466 | 4529 |
4467 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4530 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4531 ASSERT(instr->value()->IsRegister()); |
| 4532 Register value = ToRegister(instr->value()); |
4468 ASSERT(!instr->key()->IsConstantOperand()); | 4533 ASSERT(!instr->key()->IsConstantOperand()); |
4469 HType type = instr->hydrogen()->value()->type(); | 4534 HType type = instr->hydrogen()->value()->type(); |
4470 SmiCheck check_needed = | 4535 SmiCheck check_needed = |
4471 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 4536 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
4472 // Compute address of modified element and store it into key register. | 4537 // Compute address of modified element and store it into key register. |
4473 __ lea(key, operand); | 4538 __ lea(key, operand); |
4474 __ RecordWrite(elements, | 4539 __ RecordWrite(elements, |
4475 key, | 4540 key, |
4476 value, | 4541 value, |
4477 GetSaveFPRegsMode(), | 4542 GetSaveFPRegsMode(), |
(...skipping 2071 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6549 FixedArray::kHeaderSize - kPointerSize)); | 6614 FixedArray::kHeaderSize - kPointerSize)); |
6550 __ bind(&done); | 6615 __ bind(&done); |
6551 } | 6616 } |
6552 | 6617 |
6553 | 6618 |
6554 #undef __ | 6619 #undef __ |
6555 | 6620 |
6556 } } // namespace v8::internal | 6621 } } // namespace v8::internal |
6557 | 6622 |
6558 #endif // V8_TARGET_ARCH_IA32 | 6623 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |