| 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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 GenerateDeferredCode() && | 96 GenerateDeferredCode() && |
| 97 GenerateJumpTable() && | 97 GenerateJumpTable() && |
| 98 GenerateSafepointTable(); | 98 GenerateSafepointTable(); |
| 99 } | 99 } |
| 100 | 100 |
| 101 | 101 |
| 102 void LCodeGen::FinishCode(Handle<Code> code) { | 102 void LCodeGen::FinishCode(Handle<Code> code) { |
| 103 ASSERT(is_done()); | 103 ASSERT(is_done()); |
| 104 code->set_stack_slots(GetStackSlotCount()); | 104 code->set_stack_slots(GetStackSlotCount()); |
| 105 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 105 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
| 106 if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); | 106 RegisterDependentCodeForEmbeddedMaps(code); |
| 107 PopulateDeoptimizationData(code); | 107 PopulateDeoptimizationData(code); |
| 108 if (!info()->IsStub()) { | 108 if (!info()->IsStub()) { |
| 109 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); | 109 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); |
| 110 } | 110 } |
| 111 info()->CommitDependencies(code); | 111 info()->CommitDependencies(code); |
| 112 } | 112 } |
| 113 | 113 |
| 114 | 114 |
| 115 void LCodeGen::Abort(BailoutReason reason) { | 115 void LCodeGen::Abort(BailoutReason reason) { |
| 116 info()->set_bailout_reason(reason); | 116 info()->set_bailout_reason(reason); |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 bool LCodeGen::GenerateDeferredCode() { | 469 bool LCodeGen::GenerateDeferredCode() { |
| 470 ASSERT(is_generating()); | 470 ASSERT(is_generating()); |
| 471 if (deferred_.length() > 0) { | 471 if (deferred_.length() > 0) { |
| 472 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 472 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
| 473 LDeferredCode* code = deferred_[i]; | 473 LDeferredCode* code = deferred_[i]; |
| 474 X87Stack copy(code->x87_stack()); | 474 X87Stack copy(code->x87_stack()); |
| 475 x87_stack_ = copy; | 475 x87_stack_ = copy; |
| 476 | 476 |
| 477 HValue* value = | 477 HValue* value = |
| 478 instructions_->at(code->instruction_index())->hydrogen_value(); | 478 instructions_->at(code->instruction_index())->hydrogen_value(); |
| 479 RecordAndWritePosition( | 479 RecordAndWritePosition(value->position()); |
| 480 chunk()->graph()->SourcePositionToScriptPosition(value->position())); | |
| 481 | 480 |
| 482 Comment(";;; <@%d,#%d> " | 481 Comment(";;; <@%d,#%d> " |
| 483 "-------------------- Deferred %s --------------------", | 482 "-------------------- Deferred %s --------------------", |
| 484 code->instruction_index(), | 483 code->instruction_index(), |
| 485 code->instr()->hydrogen_value()->id(), | 484 code->instr()->hydrogen_value()->id(), |
| 486 code->instr()->Mnemonic()); | 485 code->instr()->Mnemonic()); |
| 487 __ bind(code->entry()); | 486 __ bind(code->entry()); |
| 488 if (NeedsDeferredFrame()) { | 487 if (NeedsDeferredFrame()) { |
| 489 Comment(";;; Build frame"); | 488 Comment(";;; Build frame"); |
| 490 ASSERT(!frame_is_built_); | 489 ASSERT(!frame_is_built_); |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1172 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 1171 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 1173 int length = deoptimizations_.length(); | 1172 int length = deoptimizations_.length(); |
| 1174 if (length == 0) return; | 1173 if (length == 0) return; |
| 1175 Handle<DeoptimizationInputData> data = | 1174 Handle<DeoptimizationInputData> data = |
| 1176 factory()->NewDeoptimizationInputData(length, TENURED); | 1175 factory()->NewDeoptimizationInputData(length, TENURED); |
| 1177 | 1176 |
| 1178 Handle<ByteArray> translations = | 1177 Handle<ByteArray> translations = |
| 1179 translations_.CreateByteArray(isolate()->factory()); | 1178 translations_.CreateByteArray(isolate()->factory()); |
| 1180 data->SetTranslationByteArray(*translations); | 1179 data->SetTranslationByteArray(*translations); |
| 1181 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); | 1180 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); |
| 1182 data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); | |
| 1183 | 1181 |
| 1184 Handle<FixedArray> literals = | 1182 Handle<FixedArray> literals = |
| 1185 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); | 1183 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); |
| 1186 { AllowDeferredHandleDereference copy_handles; | 1184 { AllowDeferredHandleDereference copy_handles; |
| 1187 for (int i = 0; i < deoptimization_literals_.length(); i++) { | 1185 for (int i = 0; i < deoptimization_literals_.length(); i++) { |
| 1188 literals->set(i, *deoptimization_literals_[i]); | 1186 literals->set(i, *deoptimization_literals_[i]); |
| 1189 } | 1187 } |
| 1190 data->SetLiteralArray(*literals); | 1188 data->SetLiteralArray(*literals); |
| 1191 } | 1189 } |
| 1192 | 1190 |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1446 } | 1444 } |
| 1447 __ idiv(right_reg); | 1445 __ idiv(right_reg); |
| 1448 __ bind(&done); | 1446 __ bind(&done); |
| 1449 } | 1447 } |
| 1450 } | 1448 } |
| 1451 | 1449 |
| 1452 | 1450 |
| 1453 void LCodeGen::DoDivI(LDivI* instr) { | 1451 void LCodeGen::DoDivI(LDivI* instr) { |
| 1454 if (!instr->is_flooring() && instr->hydrogen()->RightIsPowerOf2()) { | 1452 if (!instr->is_flooring() && instr->hydrogen()->RightIsPowerOf2()) { |
| 1455 Register dividend = ToRegister(instr->left()); | 1453 Register dividend = ToRegister(instr->left()); |
| 1456 HDiv* hdiv = instr->hydrogen(); | 1454 int32_t divisor = instr->hydrogen()->right()->GetInteger32Constant(); |
| 1457 int32_t divisor = hdiv->right()->GetInteger32Constant(); | 1455 int32_t test_value = 0; |
| 1458 Register result = ToRegister(instr->result()); | 1456 int32_t power = 0; |
| 1459 ASSERT(!result.is(dividend)); | |
| 1460 | 1457 |
| 1461 // Check for (0 / -x) that will produce negative zero. | 1458 if (divisor > 0) { |
| 1462 if (hdiv->left()->RangeCanInclude(0) && divisor < 0 && | 1459 test_value = divisor - 1; |
| 1463 hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1460 power = WhichPowerOf2(divisor); |
| 1464 __ test(dividend, Operand(dividend)); | 1461 } else { |
| 1465 DeoptimizeIf(zero, instr->environment()); | 1462 // Check for (0 / -x) that will produce negative zero. |
| 1463 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1464 __ test(dividend, Operand(dividend)); |
| 1465 DeoptimizeIf(zero, instr->environment()); |
| 1466 } |
| 1467 // Check for (kMinInt / -1). |
| 1468 if (divisor == -1 && instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1469 __ cmp(dividend, kMinInt); |
| 1470 DeoptimizeIf(zero, instr->environment()); |
| 1471 } |
| 1472 test_value = - divisor - 1; |
| 1473 power = WhichPowerOf2(-divisor); |
| 1466 } | 1474 } |
| 1467 // Check for (kMinInt / -1). | 1475 |
| 1468 if (hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1 && | 1476 if (test_value != 0) { |
| 1469 hdiv->CheckFlag(HValue::kCanOverflow)) { | 1477 if (instr->hydrogen()->CheckFlag( |
| 1470 __ cmp(dividend, kMinInt); | 1478 HInstruction::kAllUsesTruncatingToInt32)) { |
| 1471 DeoptimizeIf(zero, instr->environment()); | 1479 Label done, negative; |
| 1480 __ cmp(dividend, 0); |
| 1481 __ j(less, &negative, Label::kNear); |
| 1482 __ sar(dividend, power); |
| 1483 if (divisor < 0) __ neg(dividend); |
| 1484 __ jmp(&done, Label::kNear); |
| 1485 |
| 1486 __ bind(&negative); |
| 1487 __ neg(dividend); |
| 1488 __ sar(dividend, power); |
| 1489 if (divisor > 0) __ neg(dividend); |
| 1490 __ bind(&done); |
| 1491 return; // Don't fall through to "__ neg" below. |
| 1492 } else { |
| 1493 // Deoptimize if remainder is not 0. |
| 1494 __ test(dividend, Immediate(test_value)); |
| 1495 DeoptimizeIf(not_zero, instr->environment()); |
| 1496 __ sar(dividend, power); |
| 1497 } |
| 1472 } | 1498 } |
| 1473 // Deoptimize if remainder will not be 0. | 1499 |
| 1474 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 1500 if (divisor < 0) __ neg(dividend); |
| 1475 Abs(divisor) != 1) { | 1501 |
| 1476 __ test(dividend, Immediate(Abs(divisor) - 1)); | |
| 1477 DeoptimizeIf(not_zero, instr->environment()); | |
| 1478 } | |
| 1479 __ Move(result, dividend); | |
| 1480 int32_t shift = WhichPowerOf2(Abs(divisor)); | |
| 1481 if (shift > 0) { | |
| 1482 // The arithmetic shift is always OK, the 'if' is an optimization only. | |
| 1483 if (shift > 1) __ sar(result, 31); | |
| 1484 __ shr(result, 32 - shift); | |
| 1485 __ add(result, dividend); | |
| 1486 __ sar(result, shift); | |
| 1487 } | |
| 1488 if (divisor < 0) __ neg(result); | |
| 1489 return; | 1502 return; |
| 1490 } | 1503 } |
| 1491 | 1504 |
| 1492 LOperand* right = instr->right(); | 1505 LOperand* right = instr->right(); |
| 1493 ASSERT(ToRegister(instr->result()).is(eax)); | 1506 ASSERT(ToRegister(instr->result()).is(eax)); |
| 1494 ASSERT(ToRegister(instr->left()).is(eax)); | 1507 ASSERT(ToRegister(instr->left()).is(eax)); |
| 1495 ASSERT(!ToRegister(instr->right()).is(eax)); | 1508 ASSERT(!ToRegister(instr->right()).is(eax)); |
| 1496 ASSERT(!ToRegister(instr->right()).is(edx)); | 1509 ASSERT(!ToRegister(instr->right()).is(edx)); |
| 1497 | 1510 |
| 1498 Register left_reg = eax; | 1511 Register left_reg = eax; |
| (...skipping 2617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4116 __ movsd(Operand(esp, 0), input_reg); | 4129 __ movsd(Operand(esp, 0), input_reg); |
| 4117 __ fld_d(Operand(esp, 0)); | 4130 __ fld_d(Operand(esp, 0)); |
| 4118 __ fyl2x(); | 4131 __ fyl2x(); |
| 4119 __ fstp_d(Operand(esp, 0)); | 4132 __ fstp_d(Operand(esp, 0)); |
| 4120 __ movsd(input_reg, Operand(esp, 0)); | 4133 __ movsd(input_reg, Operand(esp, 0)); |
| 4121 __ add(Operand(esp), Immediate(kDoubleSize)); | 4134 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 4122 __ bind(&done); | 4135 __ bind(&done); |
| 4123 } | 4136 } |
| 4124 | 4137 |
| 4125 | 4138 |
| 4126 void LCodeGen::DoMathClz32(LMathClz32* instr) { | |
| 4127 CpuFeatureScope scope(masm(), SSE2); | |
| 4128 Register input = ToRegister(instr->value()); | |
| 4129 Register result = ToRegister(instr->result()); | |
| 4130 Label not_zero_input; | |
| 4131 __ bsr(result, input); | |
| 4132 | |
| 4133 __ j(not_zero, ¬_zero_input); | |
| 4134 __ Set(result, Immediate(63)); // 63^31 == 32 | |
| 4135 | |
| 4136 __ bind(¬_zero_input); | |
| 4137 __ xor_(result, Immediate(31)); // for x in [0..31], 31^x == 31-x. | |
| 4138 } | |
| 4139 | |
| 4140 | |
| 4141 void LCodeGen::DoMathExp(LMathExp* instr) { | 4139 void LCodeGen::DoMathExp(LMathExp* instr) { |
| 4142 CpuFeatureScope scope(masm(), SSE2); | 4140 CpuFeatureScope scope(masm(), SSE2); |
| 4143 XMMRegister input = ToDoubleRegister(instr->value()); | 4141 XMMRegister input = ToDoubleRegister(instr->value()); |
| 4144 XMMRegister result = ToDoubleRegister(instr->result()); | 4142 XMMRegister result = ToDoubleRegister(instr->result()); |
| 4145 XMMRegister temp0 = double_scratch0(); | 4143 XMMRegister temp0 = double_scratch0(); |
| 4146 Register temp1 = ToRegister(instr->temp1()); | 4144 Register temp1 = ToRegister(instr->temp1()); |
| 4147 Register temp2 = ToRegister(instr->temp2()); | 4145 Register temp2 = ToRegister(instr->temp2()); |
| 4148 | 4146 |
| 4149 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); | 4147 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); |
| 4150 } | 4148 } |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4284 __ mov(operand, Immediate(ToInteger32(operand_value))); | 4282 __ mov(operand, Immediate(ToInteger32(operand_value))); |
| 4285 } else { | 4283 } else { |
| 4286 Register value = ToRegister(instr->value()); | 4284 Register value = ToRegister(instr->value()); |
| 4287 __ Store(value, operand, representation); | 4285 __ Store(value, operand, representation); |
| 4288 } | 4286 } |
| 4289 return; | 4287 return; |
| 4290 } | 4288 } |
| 4291 | 4289 |
| 4292 Register object = ToRegister(instr->object()); | 4290 Register object = ToRegister(instr->object()); |
| 4293 Handle<Map> transition = instr->transition(); | 4291 Handle<Map> transition = instr->transition(); |
| 4294 SmiCheck check_needed = | |
| 4295 instr->hydrogen()->value()->IsHeapObject() | |
| 4296 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | |
| 4297 | 4292 |
| 4298 if (FLAG_track_fields && representation.IsSmi()) { | 4293 if (FLAG_track_fields && representation.IsSmi()) { |
| 4299 if (instr->value()->IsConstantOperand()) { | 4294 if (instr->value()->IsConstantOperand()) { |
| 4300 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4295 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4301 if (!IsSmi(operand_value)) { | 4296 if (!IsSmi(operand_value)) { |
| 4302 DeoptimizeIf(no_condition, instr->environment()); | 4297 DeoptimizeIf(no_condition, instr->environment()); |
| 4303 } | 4298 } |
| 4304 } | 4299 } |
| 4305 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 4300 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
| 4306 if (instr->value()->IsConstantOperand()) { | 4301 if (instr->value()->IsConstantOperand()) { |
| 4307 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4302 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4308 if (IsInteger32(operand_value)) { | 4303 if (IsInteger32(operand_value)) { |
| 4309 DeoptimizeIf(no_condition, instr->environment()); | 4304 DeoptimizeIf(no_condition, instr->environment()); |
| 4310 } | 4305 } |
| 4311 } else { | 4306 } else { |
| 4312 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 4307 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
| 4313 Register value = ToRegister(instr->value()); | 4308 Register value = ToRegister(instr->value()); |
| 4314 __ test(value, Immediate(kSmiTagMask)); | 4309 __ test(value, Immediate(kSmiTagMask)); |
| 4315 DeoptimizeIf(zero, instr->environment()); | 4310 DeoptimizeIf(zero, instr->environment()); |
| 4316 | |
| 4317 // We know that value is a smi now, so we can omit the check below. | |
| 4318 check_needed = OMIT_SMI_CHECK; | |
| 4319 } | 4311 } |
| 4320 } | 4312 } |
| 4321 } else if (representation.IsDouble()) { | 4313 } else if (representation.IsDouble()) { |
| 4322 ASSERT(transition.is_null()); | 4314 ASSERT(transition.is_null()); |
| 4323 ASSERT(access.IsInobject()); | 4315 ASSERT(access.IsInobject()); |
| 4324 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 4316 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 4325 if (CpuFeatures::IsSupported(SSE2)) { | 4317 if (CpuFeatures::IsSupported(SSE2)) { |
| 4326 CpuFeatureScope scope(masm(), SSE2); | 4318 CpuFeatureScope scope(masm(), SSE2); |
| 4327 XMMRegister value = ToDoubleRegister(instr->value()); | 4319 XMMRegister value = ToDoubleRegister(instr->value()); |
| 4328 __ movsd(FieldOperand(object, offset), value); | 4320 __ movsd(FieldOperand(object, offset), value); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4346 HeapObject::kMapOffset, | 4338 HeapObject::kMapOffset, |
| 4347 temp_map, | 4339 temp_map, |
| 4348 temp, | 4340 temp, |
| 4349 GetSaveFPRegsMode(), | 4341 GetSaveFPRegsMode(), |
| 4350 OMIT_REMEMBERED_SET, | 4342 OMIT_REMEMBERED_SET, |
| 4351 OMIT_SMI_CHECK); | 4343 OMIT_SMI_CHECK); |
| 4352 } | 4344 } |
| 4353 } | 4345 } |
| 4354 | 4346 |
| 4355 // Do the store. | 4347 // Do the store. |
| 4348 SmiCheck check_needed = |
| 4349 instr->hydrogen()->value()->IsHeapObject() |
| 4350 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 4351 |
| 4356 Register write_register = object; | 4352 Register write_register = object; |
| 4357 if (!access.IsInobject()) { | 4353 if (!access.IsInobject()) { |
| 4358 write_register = ToRegister(instr->temp()); | 4354 write_register = ToRegister(instr->temp()); |
| 4359 __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); | 4355 __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 4360 } | 4356 } |
| 4361 | 4357 |
| 4362 MemOperand operand = FieldOperand(write_register, offset); | 4358 MemOperand operand = FieldOperand(write_register, offset); |
| 4363 if (instr->value()->IsConstantOperand()) { | 4359 if (instr->value()->IsConstantOperand()) { |
| 4364 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4360 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4365 if (operand_value->IsRegister()) { | 4361 if (operand_value->IsRegister()) { |
| (...skipping 1904 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6270 FixedArray::kHeaderSize - kPointerSize)); | 6266 FixedArray::kHeaderSize - kPointerSize)); |
| 6271 __ bind(&done); | 6267 __ bind(&done); |
| 6272 } | 6268 } |
| 6273 | 6269 |
| 6274 | 6270 |
| 6275 #undef __ | 6271 #undef __ |
| 6276 | 6272 |
| 6277 } } // namespace v8::internal | 6273 } } // namespace v8::internal |
| 6278 | 6274 |
| 6279 #endif // V8_TARGET_ARCH_IA32 | 6275 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |