| 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 GenerateDeferredCode() && | 77 GenerateDeferredCode() && |
| 78 GenerateDeoptJumpTable() && | 78 GenerateDeoptJumpTable() && |
| 79 GenerateSafepointTable(); | 79 GenerateSafepointTable(); |
| 80 } | 80 } |
| 81 | 81 |
| 82 | 82 |
| 83 void LCodeGen::FinishCode(Handle<Code> code) { | 83 void LCodeGen::FinishCode(Handle<Code> code) { |
| 84 ASSERT(is_done()); | 84 ASSERT(is_done()); |
| 85 code->set_stack_slots(GetStackSlotCount()); | 85 code->set_stack_slots(GetStackSlotCount()); |
| 86 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 86 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
| 87 if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); | 87 RegisterDependentCodeForEmbeddedMaps(code); |
| 88 PopulateDeoptimizationData(code); | 88 PopulateDeoptimizationData(code); |
| 89 info()->CommitDependencies(code); | 89 info()->CommitDependencies(code); |
| 90 } | 90 } |
| 91 | 91 |
| 92 | 92 |
| 93 void LCodeGen::Abort(BailoutReason reason) { | 93 void LCodeGen::Abort(BailoutReason reason) { |
| 94 info()->set_bailout_reason(reason); | 94 info()->set_bailout_reason(reason); |
| 95 status_ = ABORTED; | 95 status_ = ABORTED; |
| 96 } | 96 } |
| 97 | 97 |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 | 270 |
| 271 | 271 |
| 272 bool LCodeGen::GenerateDeferredCode() { | 272 bool LCodeGen::GenerateDeferredCode() { |
| 273 ASSERT(is_generating()); | 273 ASSERT(is_generating()); |
| 274 if (deferred_.length() > 0) { | 274 if (deferred_.length() > 0) { |
| 275 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 275 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
| 276 LDeferredCode* code = deferred_[i]; | 276 LDeferredCode* code = deferred_[i]; |
| 277 | 277 |
| 278 HValue* value = | 278 HValue* value = |
| 279 instructions_->at(code->instruction_index())->hydrogen_value(); | 279 instructions_->at(code->instruction_index())->hydrogen_value(); |
| 280 RecordAndWritePosition( | 280 RecordAndWritePosition(value->position()); |
| 281 chunk()->graph()->SourcePositionToScriptPosition(value->position())); | |
| 282 | 281 |
| 283 Comment(";;; <@%d,#%d> " | 282 Comment(";;; <@%d,#%d> " |
| 284 "-------------------- Deferred %s --------------------", | 283 "-------------------- Deferred %s --------------------", |
| 285 code->instruction_index(), | 284 code->instruction_index(), |
| 286 code->instr()->hydrogen_value()->id(), | 285 code->instr()->hydrogen_value()->id(), |
| 287 code->instr()->Mnemonic()); | 286 code->instr()->Mnemonic()); |
| 288 __ bind(code->entry()); | 287 __ bind(code->entry()); |
| 289 if (NeedsDeferredFrame()) { | 288 if (NeedsDeferredFrame()) { |
| 290 Comment(";;; Build frame"); | 289 Comment(";;; Build frame"); |
| 291 ASSERT(!frame_is_built_); | 290 ASSERT(!frame_is_built_); |
| (...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 899 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 901 int length = deoptimizations_.length(); | 900 int length = deoptimizations_.length(); |
| 902 if (length == 0) return; | 901 if (length == 0) return; |
| 903 Handle<DeoptimizationInputData> data = | 902 Handle<DeoptimizationInputData> data = |
| 904 factory()->NewDeoptimizationInputData(length, TENURED); | 903 factory()->NewDeoptimizationInputData(length, TENURED); |
| 905 | 904 |
| 906 Handle<ByteArray> translations = | 905 Handle<ByteArray> translations = |
| 907 translations_.CreateByteArray(isolate()->factory()); | 906 translations_.CreateByteArray(isolate()->factory()); |
| 908 data->SetTranslationByteArray(*translations); | 907 data->SetTranslationByteArray(*translations); |
| 909 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); | 908 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); |
| 910 data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); | |
| 911 | 909 |
| 912 Handle<FixedArray> literals = | 910 Handle<FixedArray> literals = |
| 913 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); | 911 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); |
| 914 { AllowDeferredHandleDereference copy_handles; | 912 { AllowDeferredHandleDereference copy_handles; |
| 915 for (int i = 0; i < deoptimization_literals_.length(); i++) { | 913 for (int i = 0; i < deoptimization_literals_.length(); i++) { |
| 916 literals->set(i, *deoptimization_literals_[i]); | 914 literals->set(i, *deoptimization_literals_[i]); |
| 917 } | 915 } |
| 918 data->SetLiteralArray(*literals); | 916 data->SetLiteralArray(*literals); |
| 919 } | 917 } |
| 920 | 918 |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1336 // it gets implemented. | 1334 // it gets implemented. |
| 1337 __ mul(scratch, result, ip); | 1335 __ mul(scratch, result, ip); |
| 1338 __ sub(remainder, dividend, scratch); | 1336 __ sub(remainder, dividend, scratch); |
| 1339 } | 1337 } |
| 1340 } | 1338 } |
| 1341 } | 1339 } |
| 1342 | 1340 |
| 1343 | 1341 |
| 1344 void LCodeGen::DoDivI(LDivI* instr) { | 1342 void LCodeGen::DoDivI(LDivI* instr) { |
| 1345 if (!instr->is_flooring() && instr->hydrogen()->RightIsPowerOf2()) { | 1343 if (!instr->is_flooring() && instr->hydrogen()->RightIsPowerOf2()) { |
| 1346 Register dividend = ToRegister(instr->left()); | 1344 const Register dividend = ToRegister(instr->left()); |
| 1347 HDiv* hdiv = instr->hydrogen(); | 1345 const Register result = ToRegister(instr->result()); |
| 1348 int32_t divisor = hdiv->right()->GetInteger32Constant(); | 1346 int32_t divisor = instr->hydrogen()->right()->GetInteger32Constant(); |
| 1349 Register result = ToRegister(instr->result()); | 1347 int32_t test_value = 0; |
| 1350 ASSERT(!result.is(dividend)); | 1348 int32_t power = 0; |
| 1351 | 1349 |
| 1352 // Check for (0 / -x) that will produce negative zero. | 1350 if (divisor > 0) { |
| 1353 if (hdiv->left()->RangeCanInclude(0) && divisor < 0 && | 1351 test_value = divisor - 1; |
| 1354 hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1352 power = WhichPowerOf2(divisor); |
| 1355 __ cmp(dividend, Operand::Zero()); | 1353 } else { |
| 1356 DeoptimizeIf(eq, instr->environment()); | 1354 // Check for (0 / -x) that will produce negative zero. |
| 1355 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1356 __ cmp(dividend, Operand::Zero()); |
| 1357 DeoptimizeIf(eq, instr->environment()); |
| 1358 } |
| 1359 // Check for (kMinInt / -1). |
| 1360 if (divisor == -1 && instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1361 __ cmp(dividend, Operand(kMinInt)); |
| 1362 DeoptimizeIf(eq, instr->environment()); |
| 1363 } |
| 1364 test_value = - divisor - 1; |
| 1365 power = WhichPowerOf2(-divisor); |
| 1357 } | 1366 } |
| 1358 // Check for (kMinInt / -1). | 1367 |
| 1359 if (hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1 && | 1368 if (test_value != 0) { |
| 1360 hdiv->CheckFlag(HValue::kCanOverflow)) { | 1369 if (instr->hydrogen()->CheckFlag( |
| 1361 __ cmp(dividend, Operand(kMinInt)); | 1370 HInstruction::kAllUsesTruncatingToInt32)) { |
| 1362 DeoptimizeIf(eq, instr->environment()); | 1371 __ sub(result, dividend, Operand::Zero(), SetCC); |
| 1372 __ rsb(result, result, Operand::Zero(), LeaveCC, lt); |
| 1373 __ mov(result, Operand(result, ASR, power)); |
| 1374 if (divisor > 0) __ rsb(result, result, Operand::Zero(), LeaveCC, lt); |
| 1375 if (divisor < 0) __ rsb(result, result, Operand::Zero(), LeaveCC, gt); |
| 1376 return; // Don't fall through to "__ rsb" below. |
| 1377 } else { |
| 1378 // Deoptimize if remainder is not 0. |
| 1379 __ tst(dividend, Operand(test_value)); |
| 1380 DeoptimizeIf(ne, instr->environment()); |
| 1381 __ mov(result, Operand(dividend, ASR, power)); |
| 1382 if (divisor < 0) __ rsb(result, result, Operand(0)); |
| 1383 } |
| 1384 } else { |
| 1385 if (divisor < 0) { |
| 1386 __ rsb(result, dividend, Operand(0)); |
| 1387 } else { |
| 1388 __ Move(result, dividend); |
| 1389 } |
| 1363 } | 1390 } |
| 1364 // Deoptimize if remainder will not be 0. | 1391 |
| 1365 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | |
| 1366 Abs(divisor) != 1) { | |
| 1367 __ tst(dividend, Operand(Abs(divisor) - 1)); | |
| 1368 DeoptimizeIf(ne, instr->environment()); | |
| 1369 } | |
| 1370 if (divisor == -1) { // Nice shortcut, not needed for correctness. | |
| 1371 __ rsb(result, dividend, Operand(0)); | |
| 1372 return; | |
| 1373 } | |
| 1374 int32_t shift = WhichPowerOf2(Abs(divisor)); | |
| 1375 if (shift == 0) { | |
| 1376 __ mov(result, dividend); | |
| 1377 } else if (shift == 1) { | |
| 1378 __ add(result, dividend, Operand(dividend, LSR, 31)); | |
| 1379 } else { | |
| 1380 __ mov(result, Operand(dividend, ASR, 31)); | |
| 1381 __ add(result, dividend, Operand(result, LSR, 32 - shift)); | |
| 1382 } | |
| 1383 if (shift > 0) __ mov(result, Operand(result, ASR, shift)); | |
| 1384 if (divisor < 0) __ rsb(result, result, Operand(0)); | |
| 1385 return; | 1392 return; |
| 1386 } | 1393 } |
| 1387 | 1394 |
| 1388 const Register left = ToRegister(instr->left()); | 1395 const Register left = ToRegister(instr->left()); |
| 1389 const Register right = ToRegister(instr->right()); | 1396 const Register right = ToRegister(instr->right()); |
| 1390 const Register result = ToRegister(instr->result()); | 1397 const Register result = ToRegister(instr->result()); |
| 1391 | 1398 |
| 1392 // Check for x / 0. | 1399 // Check for x / 0. |
| 1393 if (instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { | 1400 if (instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1394 __ cmp(right, Operand::Zero()); | 1401 __ cmp(right, Operand::Zero()); |
| (...skipping 2466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3861 | 3868 |
| 3862 void LCodeGen::DoMathLog(LMathLog* instr) { | 3869 void LCodeGen::DoMathLog(LMathLog* instr) { |
| 3863 __ PrepareCallCFunction(0, 1, scratch0()); | 3870 __ PrepareCallCFunction(0, 1, scratch0()); |
| 3864 __ MovToFloatParameter(ToDoubleRegister(instr->value())); | 3871 __ MovToFloatParameter(ToDoubleRegister(instr->value())); |
| 3865 __ CallCFunction(ExternalReference::math_log_double_function(isolate()), | 3872 __ CallCFunction(ExternalReference::math_log_double_function(isolate()), |
| 3866 0, 1); | 3873 0, 1); |
| 3867 __ MovFromFloatResult(ToDoubleRegister(instr->result())); | 3874 __ MovFromFloatResult(ToDoubleRegister(instr->result())); |
| 3868 } | 3875 } |
| 3869 | 3876 |
| 3870 | 3877 |
| 3871 void LCodeGen::DoMathClz32(LMathClz32* instr) { | |
| 3872 Register input = ToRegister(instr->value()); | |
| 3873 Register result = ToRegister(instr->result()); | |
| 3874 __ clz(result, input); | |
| 3875 } | |
| 3876 | |
| 3877 | |
| 3878 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3878 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3879 ASSERT(ToRegister(instr->context()).is(cp)); | 3879 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3880 ASSERT(ToRegister(instr->function()).is(r1)); | 3880 ASSERT(ToRegister(instr->function()).is(r1)); |
| 3881 ASSERT(instr->HasPointerMap()); | 3881 ASSERT(instr->HasPointerMap()); |
| 3882 | 3882 |
| 3883 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3883 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 3884 if (known_function.is_null()) { | 3884 if (known_function.is_null()) { |
| 3885 LPointerMap* pointers = instr->pointer_map(); | 3885 LPointerMap* pointers = instr->pointer_map(); |
| 3886 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3886 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3887 ParameterCount count(instr->arity()); | 3887 ParameterCount count(instr->arity()); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4044 int offset = access.offset(); | 4044 int offset = access.offset(); |
| 4045 | 4045 |
| 4046 if (access.IsExternalMemory()) { | 4046 if (access.IsExternalMemory()) { |
| 4047 Register value = ToRegister(instr->value()); | 4047 Register value = ToRegister(instr->value()); |
| 4048 MemOperand operand = MemOperand(object, offset); | 4048 MemOperand operand = MemOperand(object, offset); |
| 4049 __ Store(value, operand, representation); | 4049 __ Store(value, operand, representation); |
| 4050 return; | 4050 return; |
| 4051 } | 4051 } |
| 4052 | 4052 |
| 4053 Handle<Map> transition = instr->transition(); | 4053 Handle<Map> transition = instr->transition(); |
| 4054 SmiCheck check_needed = | |
| 4055 instr->hydrogen()->value()->IsHeapObject() | |
| 4056 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | |
| 4057 | 4054 |
| 4058 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 4055 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
| 4059 Register value = ToRegister(instr->value()); | 4056 Register value = ToRegister(instr->value()); |
| 4060 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 4057 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
| 4061 __ SmiTst(value); | 4058 __ SmiTst(value); |
| 4062 DeoptimizeIf(eq, instr->environment()); | 4059 DeoptimizeIf(eq, instr->environment()); |
| 4063 | |
| 4064 // We know that value is a smi now, so we can omit the check below. | |
| 4065 check_needed = OMIT_SMI_CHECK; | |
| 4066 } | 4060 } |
| 4067 } else if (representation.IsDouble()) { | 4061 } else if (representation.IsDouble()) { |
| 4068 ASSERT(transition.is_null()); | 4062 ASSERT(transition.is_null()); |
| 4069 ASSERT(access.IsInobject()); | 4063 ASSERT(access.IsInobject()); |
| 4070 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 4064 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 4071 DwVfpRegister value = ToDoubleRegister(instr->value()); | 4065 DwVfpRegister value = ToDoubleRegister(instr->value()); |
| 4072 __ vstr(value, FieldMemOperand(object, offset)); | 4066 __ vstr(value, FieldMemOperand(object, offset)); |
| 4073 return; | 4067 return; |
| 4074 } | 4068 } |
| 4075 | 4069 |
| 4076 if (!transition.is_null()) { | 4070 if (!transition.is_null()) { |
| 4077 __ mov(scratch, Operand(transition)); | 4071 __ mov(scratch, Operand(transition)); |
| 4078 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 4072 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 4079 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { | 4073 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { |
| 4080 Register temp = ToRegister(instr->temp()); | 4074 Register temp = ToRegister(instr->temp()); |
| 4081 // Update the write barrier for the map field. | 4075 // Update the write barrier for the map field. |
| 4082 __ RecordWriteField(object, | 4076 __ RecordWriteField(object, |
| 4083 HeapObject::kMapOffset, | 4077 HeapObject::kMapOffset, |
| 4084 scratch, | 4078 scratch, |
| 4085 temp, | 4079 temp, |
| 4086 GetLinkRegisterState(), | 4080 GetLinkRegisterState(), |
| 4087 kSaveFPRegs, | 4081 kSaveFPRegs, |
| 4088 OMIT_REMEMBERED_SET, | 4082 OMIT_REMEMBERED_SET, |
| 4089 OMIT_SMI_CHECK); | 4083 OMIT_SMI_CHECK); |
| 4090 } | 4084 } |
| 4091 } | 4085 } |
| 4092 | 4086 |
| 4093 // Do the store. | 4087 // Do the store. |
| 4094 Register value = ToRegister(instr->value()); | 4088 Register value = ToRegister(instr->value()); |
| 4089 SmiCheck check_needed = |
| 4090 instr->hydrogen()->value()->IsHeapObject() |
| 4091 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 4095 if (access.IsInobject()) { | 4092 if (access.IsInobject()) { |
| 4096 MemOperand operand = FieldMemOperand(object, offset); | 4093 MemOperand operand = FieldMemOperand(object, offset); |
| 4097 __ Store(value, operand, representation); | 4094 __ Store(value, operand, representation); |
| 4098 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4095 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4099 // Update the write barrier for the object for in-object properties. | 4096 // Update the write barrier for the object for in-object properties. |
| 4100 __ RecordWriteField(object, | 4097 __ RecordWriteField(object, |
| 4101 offset, | 4098 offset, |
| 4102 value, | 4099 value, |
| 4103 scratch, | 4100 scratch, |
| 4104 GetLinkRegisterState(), | 4101 GetLinkRegisterState(), |
| (...skipping 1637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5742 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5739 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
| 5743 __ ldr(result, FieldMemOperand(scratch, | 5740 __ ldr(result, FieldMemOperand(scratch, |
| 5744 FixedArray::kHeaderSize - kPointerSize)); | 5741 FixedArray::kHeaderSize - kPointerSize)); |
| 5745 __ bind(&done); | 5742 __ bind(&done); |
| 5746 } | 5743 } |
| 5747 | 5744 |
| 5748 | 5745 |
| 5749 #undef __ | 5746 #undef __ |
| 5750 | 5747 |
| 5751 } } // namespace v8::internal | 5748 } } // namespace v8::internal |
| OLD | NEW |