| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 #ifdef DEBUG | 192 #ifdef DEBUG |
| 193 node = Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_; | 193 node = Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_; |
| 194 while (node != NULL) { | 194 while (node != NULL) { |
| 195 ASSERT(node != reinterpret_cast<DeoptimizingCodeListNode*>(data)); | 195 ASSERT(node != reinterpret_cast<DeoptimizingCodeListNode*>(data)); |
| 196 node = node->next(); | 196 node = node->next(); |
| 197 } | 197 } |
| 198 #endif | 198 #endif |
| 199 } | 199 } |
| 200 | 200 |
| 201 | 201 |
| 202 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) { | 202 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer, |
| 203 Isolate* isolate) { |
| 203 deoptimizer->DoComputeOutputFrames(); | 204 deoptimizer->DoComputeOutputFrames(); |
| 204 } | 205 } |
| 205 | 206 |
| 206 | 207 |
| 207 Deoptimizer::Deoptimizer(Isolate* isolate, | 208 Deoptimizer::Deoptimizer(Isolate* isolate, |
| 208 JSFunction* function, | 209 JSFunction* function, |
| 209 BailoutType type, | 210 BailoutType type, |
| 210 unsigned bailout_id, | 211 unsigned bailout_id, |
| 211 Address from, | 212 Address from, |
| 212 int fp_to_sp_delta) | 213 int fp_to_sp_delta) |
| (...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 } | 927 } |
| 927 | 928 |
| 928 | 929 |
| 929 LargeObjectChunk* Deoptimizer::CreateCode(BailoutType type) { | 930 LargeObjectChunk* Deoptimizer::CreateCode(BailoutType type) { |
| 930 // We cannot run this if the serializer is enabled because this will | 931 // We cannot run this if the serializer is enabled because this will |
| 931 // cause us to emit relocation information for the external | 932 // cause us to emit relocation information for the external |
| 932 // references. This is fine because the deoptimizer's code section | 933 // references. This is fine because the deoptimizer's code section |
| 933 // isn't meant to be serialized at all. | 934 // isn't meant to be serialized at all. |
| 934 ASSERT(!Serializer::enabled()); | 935 ASSERT(!Serializer::enabled()); |
| 935 | 936 |
| 936 MacroAssembler masm(Isolate::Current(), NULL, 16 * KB); | 937 MacroAssembler masm(NULL, 16 * KB); |
| 937 masm.set_emit_debug_code(false); | 938 masm.set_emit_debug_code(false); |
| 938 GenerateDeoptimizationEntries(&masm, kNumberOfEntries, type); | 939 GenerateDeoptimizationEntries(&masm, kNumberOfEntries, type); |
| 939 CodeDesc desc; | 940 CodeDesc desc; |
| 940 masm.GetCode(&desc); | 941 masm.GetCode(&desc); |
| 941 ASSERT(desc.reloc_size == 0); | 942 ASSERT(desc.reloc_size == 0); |
| 942 | 943 |
| 943 LargeObjectChunk* chunk = LargeObjectChunk::New(desc.instr_size, EXECUTABLE); | 944 LargeObjectChunk* chunk = LargeObjectChunk::New(desc.instr_size, EXECUTABLE); |
| 944 memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size); | 945 memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size); |
| 945 CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size); | 946 CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size); |
| 946 return chunk; | 947 return chunk; |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1187 Deoptimizer::HandleWeakDeoptimizedCode); | 1188 Deoptimizer::HandleWeakDeoptimizedCode); |
| 1188 } | 1189 } |
| 1189 | 1190 |
| 1190 | 1191 |
| 1191 DeoptimizingCodeListNode::~DeoptimizingCodeListNode() { | 1192 DeoptimizingCodeListNode::~DeoptimizingCodeListNode() { |
| 1192 GlobalHandles* global_handles = Isolate::Current()->global_handles(); | 1193 GlobalHandles* global_handles = Isolate::Current()->global_handles(); |
| 1193 global_handles->Destroy(reinterpret_cast<Object**>(code_.location())); | 1194 global_handles->Destroy(reinterpret_cast<Object**>(code_.location())); |
| 1194 } | 1195 } |
| 1195 | 1196 |
| 1196 | 1197 |
| 1197 // We can't intermix stack decoding and allocations because | |
| 1198 // deoptimization infrastracture is not GC safe. | |
| 1199 // Thus we build a temporary structure in malloced space. | |
| 1200 SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator, | |
| 1201 DeoptimizationInputData* data, | |
| 1202 JavaScriptFrame* frame) { | |
| 1203 Translation::Opcode opcode = | |
| 1204 static_cast<Translation::Opcode>(iterator->Next()); | |
| 1205 | |
| 1206 switch (opcode) { | |
| 1207 case Translation::BEGIN: | |
| 1208 case Translation::FRAME: | |
| 1209 // Peeled off before getting here. | |
| 1210 break; | |
| 1211 | |
| 1212 case Translation::ARGUMENTS_OBJECT: | |
| 1213 // This can be only emitted for local slots not for argument slots. | |
| 1214 break; | |
| 1215 | |
| 1216 case Translation::REGISTER: | |
| 1217 case Translation::INT32_REGISTER: | |
| 1218 case Translation::DOUBLE_REGISTER: | |
| 1219 case Translation::DUPLICATE: | |
| 1220 // We are at safepoint which corresponds to call. All registers are | |
| 1221 // saved by caller so there would be no live registers at this | |
| 1222 // point. Thus these translation commands should not be used. | |
| 1223 break; | |
| 1224 | |
| 1225 case Translation::STACK_SLOT: { | |
| 1226 int slot_index = iterator->Next(); | |
| 1227 Address slot_addr = SlotAddress(frame, slot_index); | |
| 1228 return SlotRef(slot_addr, SlotRef::TAGGED); | |
| 1229 } | |
| 1230 | |
| 1231 case Translation::INT32_STACK_SLOT: { | |
| 1232 int slot_index = iterator->Next(); | |
| 1233 Address slot_addr = SlotAddress(frame, slot_index); | |
| 1234 return SlotRef(slot_addr, SlotRef::INT32); | |
| 1235 } | |
| 1236 | |
| 1237 case Translation::DOUBLE_STACK_SLOT: { | |
| 1238 int slot_index = iterator->Next(); | |
| 1239 Address slot_addr = SlotAddress(frame, slot_index); | |
| 1240 return SlotRef(slot_addr, SlotRef::DOUBLE); | |
| 1241 } | |
| 1242 | |
| 1243 case Translation::LITERAL: { | |
| 1244 int literal_index = iterator->Next(); | |
| 1245 return SlotRef(data->LiteralArray()->get(literal_index)); | |
| 1246 } | |
| 1247 } | |
| 1248 | |
| 1249 UNREACHABLE(); | |
| 1250 return SlotRef(); | |
| 1251 } | |
| 1252 | |
| 1253 | |
| 1254 void SlotRef::ComputeSlotMappingForArguments(JavaScriptFrame* frame, | |
| 1255 int inlined_frame_index, | |
| 1256 Vector<SlotRef>* args_slots) { | |
| 1257 AssertNoAllocation no_gc; | |
| 1258 int deopt_index = AstNode::kNoNumber; | |
| 1259 DeoptimizationInputData* data = | |
| 1260 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); | |
| 1261 TranslationIterator it(data->TranslationByteArray(), | |
| 1262 data->TranslationIndex(deopt_index)->value()); | |
| 1263 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | |
| 1264 ASSERT(opcode == Translation::BEGIN); | |
| 1265 int frame_count = it.Next(); | |
| 1266 USE(frame_count); | |
| 1267 ASSERT(frame_count > inlined_frame_index); | |
| 1268 int frames_to_skip = inlined_frame_index; | |
| 1269 while (true) { | |
| 1270 opcode = static_cast<Translation::Opcode>(it.Next()); | |
| 1271 // Skip over operands to advance to the next opcode. | |
| 1272 it.Skip(Translation::NumberOfOperandsFor(opcode)); | |
| 1273 if (opcode == Translation::FRAME) { | |
| 1274 if (frames_to_skip == 0) { | |
| 1275 // We reached the frame corresponding to the inlined function | |
| 1276 // in question. Process the translation commands for the | |
| 1277 // arguments. | |
| 1278 // | |
| 1279 // Skip the translation command for the receiver. | |
| 1280 it.Skip(Translation::NumberOfOperandsFor( | |
| 1281 static_cast<Translation::Opcode>(it.Next()))); | |
| 1282 // Compute slots for arguments. | |
| 1283 for (int i = 0; i < args_slots->length(); ++i) { | |
| 1284 (*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame); | |
| 1285 } | |
| 1286 return; | |
| 1287 } | |
| 1288 frames_to_skip--; | |
| 1289 } | |
| 1290 } | |
| 1291 | |
| 1292 UNREACHABLE(); | |
| 1293 } | |
| 1294 | |
| 1295 | |
| 1296 } } // namespace v8::internal | 1198 } } // namespace v8::internal |
| OLD | NEW |