| 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 (FLAG_weak_embedded_maps_in_optimized_code) { | 106 RegisterDependentCodeForEmbeddedMaps(code); |
| 107 RegisterDependentCodeForEmbeddedMaps(code); | |
| 108 } | |
| 109 PopulateDeoptimizationData(code); | 107 PopulateDeoptimizationData(code); |
| 110 if (!info()->IsStub()) { | 108 if (!info()->IsStub()) { |
| 111 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); | 109 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); |
| 112 } | 110 } |
| 113 info()->CommitDependencies(code); | 111 info()->CommitDependencies(code); |
| 114 } | 112 } |
| 115 | 113 |
| 116 | 114 |
| 117 void LCodeGen::Abort(BailoutReason reason) { | 115 void LCodeGen::Abort(BailoutReason reason) { |
| 118 info()->set_bailout_reason(reason); | 116 info()->set_bailout_reason(reason); |
| (...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 | 1153 |
| 1156 void LCodeGen::DeoptimizeIf(Condition cc, | 1154 void LCodeGen::DeoptimizeIf(Condition cc, |
| 1157 LEnvironment* environment) { | 1155 LEnvironment* environment) { |
| 1158 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 1156 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
| 1159 ? Deoptimizer::LAZY | 1157 ? Deoptimizer::LAZY |
| 1160 : Deoptimizer::EAGER; | 1158 : Deoptimizer::EAGER; |
| 1161 DeoptimizeIf(cc, environment, bailout_type); | 1159 DeoptimizeIf(cc, environment, bailout_type); |
| 1162 } | 1160 } |
| 1163 | 1161 |
| 1164 | 1162 |
| 1165 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { | |
| 1166 ZoneList<Handle<Map> > maps(1, zone()); | |
| 1167 ZoneList<Handle<JSObject> > objects(1, zone()); | |
| 1168 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | |
| 1169 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { | |
| 1170 if (Code::IsWeakEmbeddedObject(code->kind(), it.rinfo()->target_object())) { | |
| 1171 if (it.rinfo()->target_object()->IsMap()) { | |
| 1172 Handle<Map> map(Map::cast(it.rinfo()->target_object())); | |
| 1173 maps.Add(map, zone()); | |
| 1174 } else if (it.rinfo()->target_object()->IsJSObject()) { | |
| 1175 Handle<JSObject> object(JSObject::cast(it.rinfo()->target_object())); | |
| 1176 objects.Add(object, zone()); | |
| 1177 } | |
| 1178 } | |
| 1179 } | |
| 1180 #ifdef VERIFY_HEAP | |
| 1181 // This disables verification of weak embedded objects after full GC. | |
| 1182 // AddDependentCode can cause a GC, which would observe the state where | |
| 1183 // this code is not yet in the depended code lists of the embedded maps. | |
| 1184 NoWeakObjectVerificationScope disable_verification_of_embedded_objects; | |
| 1185 #endif | |
| 1186 for (int i = 0; i < maps.length(); i++) { | |
| 1187 maps.at(i)->AddDependentCode(DependentCode::kWeaklyEmbeddedGroup, code); | |
| 1188 } | |
| 1189 for (int i = 0; i < objects.length(); i++) { | |
| 1190 AddWeakObjectToCodeDependency(isolate()->heap(), objects.at(i), code); | |
| 1191 } | |
| 1192 } | |
| 1193 | |
| 1194 | |
| 1195 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 1163 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 1196 int length = deoptimizations_.length(); | 1164 int length = deoptimizations_.length(); |
| 1197 if (length == 0) return; | 1165 if (length == 0) return; |
| 1198 Handle<DeoptimizationInputData> data = | 1166 Handle<DeoptimizationInputData> data = |
| 1199 factory()->NewDeoptimizationInputData(length, TENURED); | 1167 factory()->NewDeoptimizationInputData(length, TENURED); |
| 1200 | 1168 |
| 1201 Handle<ByteArray> translations = | 1169 Handle<ByteArray> translations = |
| 1202 translations_.CreateByteArray(isolate()->factory()); | 1170 translations_.CreateByteArray(isolate()->factory()); |
| 1203 data->SetTranslationByteArray(*translations); | 1171 data->SetTranslationByteArray(*translations); |
| 1204 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); | 1172 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); |
| (...skipping 1144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2349 } | 2317 } |
| 2350 } | 2318 } |
| 2351 | 2319 |
| 2352 | 2320 |
| 2353 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 2321 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 2354 ASSERT(ToRegister(instr->context()).is(esi)); | 2322 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2355 ASSERT(ToRegister(instr->left()).is(edx)); | 2323 ASSERT(ToRegister(instr->left()).is(edx)); |
| 2356 ASSERT(ToRegister(instr->right()).is(eax)); | 2324 ASSERT(ToRegister(instr->right()).is(eax)); |
| 2357 ASSERT(ToRegister(instr->result()).is(eax)); | 2325 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2358 | 2326 |
| 2359 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 2327 BinaryOpICStub stub(instr->op(), NO_OVERWRITE); |
| 2360 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2328 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 2361 __ nop(); // Signals no inlined code. | 2329 __ nop(); // Signals no inlined code. |
| 2362 } | 2330 } |
| 2363 | 2331 |
| 2364 | 2332 |
| 2365 template<class InstrType> | 2333 template<class InstrType> |
| 2366 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { | 2334 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { |
| 2367 int left_block = instr->TrueDestination(chunk_); | 2335 int left_block = instr->TrueDestination(chunk_); |
| 2368 int right_block = instr->FalseDestination(chunk_); | 2336 int right_block = instr->FalseDestination(chunk_); |
| 2369 | 2337 |
| (...skipping 1852 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4222 XMMRegister input = ToDoubleRegister(instr->value()); | 4190 XMMRegister input = ToDoubleRegister(instr->value()); |
| 4223 XMMRegister result = ToDoubleRegister(instr->result()); | 4191 XMMRegister result = ToDoubleRegister(instr->result()); |
| 4224 XMMRegister temp0 = double_scratch0(); | 4192 XMMRegister temp0 = double_scratch0(); |
| 4225 Register temp1 = ToRegister(instr->temp1()); | 4193 Register temp1 = ToRegister(instr->temp1()); |
| 4226 Register temp2 = ToRegister(instr->temp2()); | 4194 Register temp2 = ToRegister(instr->temp2()); |
| 4227 | 4195 |
| 4228 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); | 4196 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); |
| 4229 } | 4197 } |
| 4230 | 4198 |
| 4231 | 4199 |
| 4232 void LCodeGen::DoMathTan(LMathTan* instr) { | |
| 4233 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | |
| 4234 // Set the context register to a GC-safe fake value. Clobbering it is | |
| 4235 // OK because this instruction is marked as a call. | |
| 4236 __ Set(esi, Immediate(0)); | |
| 4237 TranscendentalCacheStub stub(TranscendentalCache::TAN, | |
| 4238 TranscendentalCacheStub::UNTAGGED); | |
| 4239 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 4240 } | |
| 4241 | |
| 4242 | |
| 4243 void LCodeGen::DoMathCos(LMathCos* instr) { | |
| 4244 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | |
| 4245 // Set the context register to a GC-safe fake value. Clobbering it is | |
| 4246 // OK because this instruction is marked as a call. | |
| 4247 __ Set(esi, Immediate(0)); | |
| 4248 TranscendentalCacheStub stub(TranscendentalCache::COS, | |
| 4249 TranscendentalCacheStub::UNTAGGED); | |
| 4250 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 4251 } | |
| 4252 | |
| 4253 | |
| 4254 void LCodeGen::DoMathSin(LMathSin* instr) { | |
| 4255 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | |
| 4256 // Set the context register to a GC-safe fake value. Clobbering it is | |
| 4257 // OK because this instruction is marked as a call. | |
| 4258 __ Set(esi, Immediate(0)); | |
| 4259 TranscendentalCacheStub stub(TranscendentalCache::SIN, | |
| 4260 TranscendentalCacheStub::UNTAGGED); | |
| 4261 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 4262 } | |
| 4263 | |
| 4264 | |
| 4265 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 4200 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 4266 ASSERT(ToRegister(instr->context()).is(esi)); | 4201 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4267 ASSERT(ToRegister(instr->function()).is(edi)); | 4202 ASSERT(ToRegister(instr->function()).is(edi)); |
| 4268 ASSERT(instr->HasPointerMap()); | 4203 ASSERT(instr->HasPointerMap()); |
| 4269 | 4204 |
| 4270 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 4205 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 4271 if (known_function.is_null()) { | 4206 if (known_function.is_null()) { |
| 4272 LPointerMap* pointers = instr->pointer_map(); | 4207 LPointerMap* pointers = instr->pointer_map(); |
| 4273 SafepointGenerator generator( | 4208 SafepointGenerator generator( |
| 4274 this, pointers, Safepoint::kLazyDeopt); | 4209 this, pointers, Safepoint::kLazyDeopt); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4419 Register function = ToRegister(instr->function()); | 4354 Register function = ToRegister(instr->function()); |
| 4420 Register code_object = ToRegister(instr->code_object()); | 4355 Register code_object = ToRegister(instr->code_object()); |
| 4421 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize)); | 4356 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize)); |
| 4422 __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); | 4357 __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); |
| 4423 } | 4358 } |
| 4424 | 4359 |
| 4425 | 4360 |
| 4426 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { | 4361 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { |
| 4427 Register result = ToRegister(instr->result()); | 4362 Register result = ToRegister(instr->result()); |
| 4428 Register base = ToRegister(instr->base_object()); | 4363 Register base = ToRegister(instr->base_object()); |
| 4429 __ lea(result, Operand(base, instr->offset())); | 4364 if (instr->offset()->IsConstantOperand()) { |
| 4365 LConstantOperand* offset = LConstantOperand::cast(instr->offset()); |
| 4366 __ lea(result, Operand(base, ToInteger32(offset))); |
| 4367 } else { |
| 4368 Register offset = ToRegister(instr->offset()); |
| 4369 __ lea(result, Operand(base, offset, times_1, 0)); |
| 4370 } |
| 4430 } | 4371 } |
| 4431 | 4372 |
| 4432 | 4373 |
| 4433 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 4374 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
| 4434 Representation representation = instr->representation(); | 4375 Representation representation = instr->representation(); |
| 4435 | 4376 |
| 4436 HObjectAccess access = instr->hydrogen()->access(); | 4377 HObjectAccess access = instr->hydrogen()->access(); |
| 4437 int offset = access.offset(); | 4378 int offset = access.offset(); |
| 4438 | 4379 |
| 4439 if (access.IsExternalMemory()) { | 4380 if (access.IsExternalMemory()) { |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4838 if (is_simple_map_transition) { | 4779 if (is_simple_map_transition) { |
| 4839 Register new_map_reg = ToRegister(instr->new_map_temp()); | 4780 Register new_map_reg = ToRegister(instr->new_map_temp()); |
| 4840 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), | 4781 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), |
| 4841 Immediate(to_map)); | 4782 Immediate(to_map)); |
| 4842 // Write barrier. | 4783 // Write barrier. |
| 4843 ASSERT_NE(instr->temp(), NULL); | 4784 ASSERT_NE(instr->temp(), NULL); |
| 4844 __ RecordWriteForMap(object_reg, to_map, new_map_reg, | 4785 __ RecordWriteForMap(object_reg, to_map, new_map_reg, |
| 4845 ToRegister(instr->temp()), | 4786 ToRegister(instr->temp()), |
| 4846 kDontSaveFPRegs); | 4787 kDontSaveFPRegs); |
| 4847 } else { | 4788 } else { |
| 4789 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4848 PushSafepointRegistersScope scope(this); | 4790 PushSafepointRegistersScope scope(this); |
| 4849 if (!object_reg.is(eax)) { | 4791 if (!object_reg.is(eax)) { |
| 4850 __ push(object_reg); | 4792 __ mov(eax, object_reg); |
| 4851 } | |
| 4852 LoadContextFromDeferred(instr->context()); | |
| 4853 if (!object_reg.is(eax)) { | |
| 4854 __ pop(eax); | |
| 4855 } | 4793 } |
| 4856 __ mov(ebx, to_map); | 4794 __ mov(ebx, to_map); |
| 4857 TransitionElementsKindStub stub(from_kind, to_kind); | 4795 TransitionElementsKindStub stub(from_kind, to_kind); |
| 4858 __ CallStub(&stub); | 4796 __ CallStub(&stub); |
| 4859 RecordSafepointWithRegisters( | 4797 RecordSafepointWithRegisters( |
| 4860 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4798 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4861 } | 4799 } |
| 4862 __ bind(¬_applicable); | 4800 __ bind(¬_applicable); |
| 4863 } | 4801 } |
| 4864 | 4802 |
| (...skipping 1566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6431 FixedArray::kHeaderSize - kPointerSize)); | 6369 FixedArray::kHeaderSize - kPointerSize)); |
| 6432 __ bind(&done); | 6370 __ bind(&done); |
| 6433 } | 6371 } |
| 6434 | 6372 |
| 6435 | 6373 |
| 6436 #undef __ | 6374 #undef __ |
| 6437 | 6375 |
| 6438 } } // namespace v8::internal | 6376 } } // namespace v8::internal |
| 6439 | 6377 |
| 6440 #endif // V8_TARGET_ARCH_IA32 | 6378 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |