| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 // Move the code to the _deoptimized_ code list. | 385 // Move the code to the _deoptimized_ code list. |
| 386 code->set_next_code_link(context->DeoptimizedCodeListHead()); | 386 code->set_next_code_link(context->DeoptimizedCodeListHead()); |
| 387 context->SetDeoptimizedCodeListHead(code); | 387 context->SetDeoptimizedCodeListHead(code); |
| 388 } else { | 388 } else { |
| 389 // Not marked; preserve this element. | 389 // Not marked; preserve this element. |
| 390 prev = code; | 390 prev = code; |
| 391 } | 391 } |
| 392 element = next; | 392 element = next; |
| 393 } | 393 } |
| 394 | 394 |
| 395 #ifdef DEBUG |
| 396 // Make sure all activations of optimized code can deopt at their current PC. |
| 397 for (StackFrameIterator it(isolate, isolate->thread_local_top()); |
| 398 !it.done(); it.Advance()) { |
| 399 StackFrame::Type type = it.frame()->type(); |
| 400 if (type == StackFrame::OPTIMIZED) { |
| 401 Code* code = it.frame()->LookupCode(); |
| 402 if (FLAG_trace_deopt) { |
| 403 JSFunction* function = |
| 404 static_cast<OptimizedFrame*>(it.frame())->function(); |
| 405 CodeTracer::Scope scope(isolate->GetCodeTracer()); |
| 406 PrintF(scope.file(), "[deoptimizer patches for lazy deopt: "); |
| 407 function->PrintName(scope.file()); |
| 408 PrintF(scope.file(), |
| 409 " / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function)); |
| 410 } |
| 411 SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc()); |
| 412 int deopt_index = safepoint.deoptimization_index(); |
| 413 CHECK(deopt_index != Safepoint::kNoDeoptimizationIndex); |
| 414 } |
| 415 } |
| 416 #endif |
| 417 |
| 395 // TODO(titzer): we need a handle scope only because of the macro assembler, | 418 // TODO(titzer): we need a handle scope only because of the macro assembler, |
| 396 // which is only used in EnsureCodeForDeoptimizationEntry. | 419 // which is only used in EnsureCodeForDeoptimizationEntry. |
| 397 HandleScope scope(isolate); | 420 HandleScope scope(isolate); |
| 421 |
| 398 // Now patch all the codes for deoptimization. | 422 // Now patch all the codes for deoptimization. |
| 399 for (int i = 0; i < codes.length(); i++) { | 423 for (int i = 0; i < codes.length(); i++) { |
| 400 // It is finally time to die, code object. | 424 // It is finally time to die, code object. |
| 401 // Do platform-specific patching to force any activations to lazy deopt. | 425 // Do platform-specific patching to force any activations to lazy deopt. |
| 402 PatchCodeForDeoptimization(isolate, codes[i]); | 426 PatchCodeForDeoptimization(isolate, codes[i]); |
| 403 | 427 |
| 404 // We might be in the middle of incremental marking with compaction. | 428 // We might be in the middle of incremental marking with compaction. |
| 405 // Tell collector to treat this code object in a special way and | 429 // Tell collector to treat this code object in a special way and |
| 406 // ignore all slots that might have been recorded on it. | 430 // ignore all slots that might have been recorded on it. |
| 407 isolate->heap()->mark_compact_collector()->InvalidateCode(codes[i]); | 431 isolate->heap()->mark_compact_collector()->InvalidateCode(codes[i]); |
| (...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 961 PrintF(trace_scope_->file(), | 985 PrintF(trace_scope_->file(), |
| 962 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 986 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 963 V8PRIxPTR " ; caller's fp\n", | 987 V8PRIxPTR " ; caller's fp\n", |
| 964 fp_value, output_offset, value); | 988 fp_value, output_offset, value); |
| 965 } | 989 } |
| 966 ASSERT(!is_bottommost || !has_alignment_padding_ || | 990 ASSERT(!is_bottommost || !has_alignment_padding_ || |
| 967 (fp_value & kPointerSize) != 0); | 991 (fp_value & kPointerSize) != 0); |
| 968 | 992 |
| 969 if (FLAG_enable_ool_constant_pool) { | 993 if (FLAG_enable_ool_constant_pool) { |
| 970 // For the bottommost output frame the constant pool pointer can be gotten | 994 // For the bottommost output frame the constant pool pointer can be gotten |
| 971 // from the input frame. For subsequent output frames, it can be gotten from | 995 // from the input frame. For subsequent output frames, it can be read from |
| 972 // the function's code. | 996 // the previous frame. |
| 973 Register constant_pool_reg = | |
| 974 JavaScriptFrame::constant_pool_pointer_register(); | |
| 975 output_offset -= kPointerSize; | 997 output_offset -= kPointerSize; |
| 976 input_offset -= kPointerSize; | 998 input_offset -= kPointerSize; |
| 977 if (is_bottommost) { | 999 if (is_bottommost) { |
| 978 value = input_->GetFrameSlot(input_offset); | 1000 value = input_->GetFrameSlot(input_offset); |
| 979 } else { | 1001 } else { |
| 980 value = reinterpret_cast<intptr_t>( | 1002 value = output_[frame_index - 1]->GetConstantPool(); |
| 981 function->shared()->code()->constant_pool()); | |
| 982 } | 1003 } |
| 983 output_frame->SetFrameSlot(output_offset, value); | 1004 output_frame->SetCallerConstantPool(output_offset, value); |
| 984 output_frame->SetConstantPool(value); | |
| 985 if (is_topmost) output_frame->SetRegister(constant_pool_reg.code(), value); | |
| 986 if (trace_scope_) { | 1005 if (trace_scope_) { |
| 987 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1006 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 988 V8PRIxPTR "; constant_pool\n", | 1007 V8PRIxPTR "; caller's constant_pool\n", |
| 989 top_address + output_offset, output_offset, value); | 1008 top_address + output_offset, output_offset, value); |
| 990 } | 1009 } |
| 991 } | 1010 } |
| 992 | 1011 |
| 993 // For the bottommost output frame the context can be gotten from the input | 1012 // For the bottommost output frame the context can be gotten from the input |
| 994 // frame. For all subsequent output frames it can be gotten from the function | 1013 // frame. For all subsequent output frames it can be gotten from the function |
| 995 // so long as we don't inline functions that need local contexts. | 1014 // so long as we don't inline functions that need local contexts. |
| 996 Register context_reg = JavaScriptFrame::context_register(); | 1015 Register context_reg = JavaScriptFrame::context_register(); |
| 997 output_offset -= kPointerSize; | 1016 output_offset -= kPointerSize; |
| 998 input_offset -= kPointerSize; | 1017 input_offset -= kPointerSize; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1036 // Compute this frame's PC, state, and continuation. | 1055 // Compute this frame's PC, state, and continuation. |
| 1037 Code* non_optimized_code = function->shared()->code(); | 1056 Code* non_optimized_code = function->shared()->code(); |
| 1038 FixedArray* raw_data = non_optimized_code->deoptimization_data(); | 1057 FixedArray* raw_data = non_optimized_code->deoptimization_data(); |
| 1039 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); | 1058 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); |
| 1040 Address start = non_optimized_code->instruction_start(); | 1059 Address start = non_optimized_code->instruction_start(); |
| 1041 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); | 1060 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); |
| 1042 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); | 1061 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); |
| 1043 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); | 1062 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); |
| 1044 output_frame->SetPc(pc_value); | 1063 output_frame->SetPc(pc_value); |
| 1045 | 1064 |
| 1065 // Update constant pool. |
| 1066 if (FLAG_enable_ool_constant_pool) { |
| 1067 intptr_t constant_pool_value = |
| 1068 reinterpret_cast<intptr_t>(non_optimized_code->constant_pool()); |
| 1069 output_frame->SetConstantPool(constant_pool_value); |
| 1070 if (is_topmost) { |
| 1071 Register constant_pool_reg = |
| 1072 JavaScriptFrame::constant_pool_pointer_register(); |
| 1073 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); |
| 1074 } |
| 1075 } |
| 1076 |
| 1046 FullCodeGenerator::State state = | 1077 FullCodeGenerator::State state = |
| 1047 FullCodeGenerator::StateField::decode(pc_and_state); | 1078 FullCodeGenerator::StateField::decode(pc_and_state); |
| 1048 output_frame->SetState(Smi::FromInt(state)); | 1079 output_frame->SetState(Smi::FromInt(state)); |
| 1049 | 1080 |
| 1050 // Set the continuation for the topmost frame. | 1081 // Set the continuation for the topmost frame. |
| 1051 if (is_topmost && bailout_type_ != DEBUGGER) { | 1082 if (is_topmost && bailout_type_ != DEBUGGER) { |
| 1052 Builtins* builtins = isolate_->builtins(); | 1083 Builtins* builtins = isolate_->builtins(); |
| 1053 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); | 1084 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); |
| 1054 if (bailout_type_ == LAZY) { | 1085 if (bailout_type_ == LAZY) { |
| 1055 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); | 1086 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1119 intptr_t fp_value = top_address + output_offset; | 1150 intptr_t fp_value = top_address + output_offset; |
| 1120 output_frame->SetFp(fp_value); | 1151 output_frame->SetFp(fp_value); |
| 1121 if (trace_scope_ != NULL) { | 1152 if (trace_scope_ != NULL) { |
| 1122 PrintF(trace_scope_->file(), | 1153 PrintF(trace_scope_->file(), |
| 1123 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1154 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 1124 V8PRIxPTR " ; caller's fp\n", | 1155 V8PRIxPTR " ; caller's fp\n", |
| 1125 fp_value, output_offset, value); | 1156 fp_value, output_offset, value); |
| 1126 } | 1157 } |
| 1127 | 1158 |
| 1128 if (FLAG_enable_ool_constant_pool) { | 1159 if (FLAG_enable_ool_constant_pool) { |
| 1129 // A marker value is used in place of the constant pool. | 1160 // Read the caller's constant pool from the previous frame. |
| 1130 output_offset -= kPointerSize; | 1161 output_offset -= kPointerSize; |
| 1131 intptr_t constant_pool = reinterpret_cast<intptr_t>( | 1162 value = output_[frame_index - 1]->GetConstantPool(); |
| 1132 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 1163 output_frame->SetCallerConstantPool(output_offset, value); |
| 1133 output_frame->SetFrameSlot(output_offset, constant_pool); | |
| 1134 if (trace_scope_) { | 1164 if (trace_scope_) { |
| 1135 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1165 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 1136 V8PRIxPTR " ; constant_pool (adaptor sentinel)\n", | 1166 V8PRIxPTR "; caller's constant_pool\n", |
| 1137 top_address + output_offset, output_offset, constant_pool); | 1167 top_address + output_offset, output_offset, value); |
| 1138 } | 1168 } |
| 1139 } | 1169 } |
| 1140 | 1170 |
| 1141 // A marker value is used in place of the context. | 1171 // A marker value is used in place of the context. |
| 1142 output_offset -= kPointerSize; | 1172 output_offset -= kPointerSize; |
| 1143 intptr_t context = reinterpret_cast<intptr_t>( | 1173 intptr_t context = reinterpret_cast<intptr_t>( |
| 1144 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 1174 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 1145 output_frame->SetFrameSlot(output_offset, context); | 1175 output_frame->SetFrameSlot(output_offset, context); |
| 1146 if (trace_scope_ != NULL) { | 1176 if (trace_scope_ != NULL) { |
| 1147 PrintF(trace_scope_->file(), | 1177 PrintF(trace_scope_->file(), |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1174 | 1204 |
| 1175 ASSERT(0 == output_offset); | 1205 ASSERT(0 == output_offset); |
| 1176 | 1206 |
| 1177 Builtins* builtins = isolate_->builtins(); | 1207 Builtins* builtins = isolate_->builtins(); |
| 1178 Code* adaptor_trampoline = | 1208 Code* adaptor_trampoline = |
| 1179 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline); | 1209 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline); |
| 1180 intptr_t pc_value = reinterpret_cast<intptr_t>( | 1210 intptr_t pc_value = reinterpret_cast<intptr_t>( |
| 1181 adaptor_trampoline->instruction_start() + | 1211 adaptor_trampoline->instruction_start() + |
| 1182 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value()); | 1212 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value()); |
| 1183 output_frame->SetPc(pc_value); | 1213 output_frame->SetPc(pc_value); |
| 1214 if (FLAG_enable_ool_constant_pool) { |
| 1215 intptr_t constant_pool_value = |
| 1216 reinterpret_cast<intptr_t>(adaptor_trampoline->constant_pool()); |
| 1217 output_frame->SetConstantPool(constant_pool_value); |
| 1218 } |
| 1184 } | 1219 } |
| 1185 | 1220 |
| 1186 | 1221 |
| 1187 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, | 1222 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, |
| 1188 int frame_index) { | 1223 int frame_index) { |
| 1189 Builtins* builtins = isolate_->builtins(); | 1224 Builtins* builtins = isolate_->builtins(); |
| 1190 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); | 1225 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); |
| 1191 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 1226 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
| 1192 unsigned height = iterator->Next(); | 1227 unsigned height = iterator->Next(); |
| 1193 unsigned height_in_bytes = height * kPointerSize; | 1228 unsigned height_in_bytes = height * kPointerSize; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 intptr_t fp_value = top_address + output_offset; | 1284 intptr_t fp_value = top_address + output_offset; |
| 1250 output_frame->SetFp(fp_value); | 1285 output_frame->SetFp(fp_value); |
| 1251 if (trace_scope_ != NULL) { | 1286 if (trace_scope_ != NULL) { |
| 1252 PrintF(trace_scope_->file(), | 1287 PrintF(trace_scope_->file(), |
| 1253 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1288 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 1254 V8PRIxPTR " ; caller's fp\n", | 1289 V8PRIxPTR " ; caller's fp\n", |
| 1255 fp_value, output_offset, value); | 1290 fp_value, output_offset, value); |
| 1256 } | 1291 } |
| 1257 | 1292 |
| 1258 if (FLAG_enable_ool_constant_pool) { | 1293 if (FLAG_enable_ool_constant_pool) { |
| 1259 // The constant pool pointer can be gotten from the previous frame. | 1294 // Read the caller's constant pool from the previous frame. |
| 1260 output_offset -= kPointerSize; | 1295 output_offset -= kPointerSize; |
| 1261 value = output_[frame_index - 1]->GetConstantPool(); | 1296 value = output_[frame_index - 1]->GetConstantPool(); |
| 1262 output_frame->SetFrameSlot(output_offset, value); | 1297 output_frame->SetCallerConstantPool(output_offset, value); |
| 1263 if (trace_scope_) { | 1298 if (trace_scope_) { |
| 1264 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1299 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 1265 V8PRIxPTR " ; constant pool\n", | 1300 V8PRIxPTR " ; caller's constant pool\n", |
| 1266 top_address + output_offset, output_offset, value); | 1301 top_address + output_offset, output_offset, value); |
| 1267 } | 1302 } |
| 1268 } | 1303 } |
| 1269 | 1304 |
| 1270 // The context can be gotten from the previous frame. | 1305 // The context can be gotten from the previous frame. |
| 1271 output_offset -= kPointerSize; | 1306 output_offset -= kPointerSize; |
| 1272 value = output_[frame_index - 1]->GetContext(); | 1307 value = output_[frame_index - 1]->GetContext(); |
| 1273 output_frame->SetFrameSlot(output_offset, value); | 1308 output_frame->SetFrameSlot(output_offset, value); |
| 1274 if (trace_scope_ != NULL) { | 1309 if (trace_scope_ != NULL) { |
| 1275 PrintF(trace_scope_->file(), | 1310 PrintF(trace_scope_->file(), |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1336 V8PRIxPTR " ; allocated receiver\n", | 1371 V8PRIxPTR " ; allocated receiver\n", |
| 1337 top_address + output_offset, output_offset, value); | 1372 top_address + output_offset, output_offset, value); |
| 1338 } | 1373 } |
| 1339 | 1374 |
| 1340 ASSERT(0 == output_offset); | 1375 ASSERT(0 == output_offset); |
| 1341 | 1376 |
| 1342 intptr_t pc = reinterpret_cast<intptr_t>( | 1377 intptr_t pc = reinterpret_cast<intptr_t>( |
| 1343 construct_stub->instruction_start() + | 1378 construct_stub->instruction_start() + |
| 1344 isolate_->heap()->construct_stub_deopt_pc_offset()->value()); | 1379 isolate_->heap()->construct_stub_deopt_pc_offset()->value()); |
| 1345 output_frame->SetPc(pc); | 1380 output_frame->SetPc(pc); |
| 1381 if (FLAG_enable_ool_constant_pool) { |
| 1382 intptr_t constant_pool_value = |
| 1383 reinterpret_cast<intptr_t>(construct_stub->constant_pool()); |
| 1384 output_frame->SetConstantPool(constant_pool_value); |
| 1385 } |
| 1346 } | 1386 } |
| 1347 | 1387 |
| 1348 | 1388 |
| 1349 void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator, | 1389 void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator, |
| 1350 int frame_index, | 1390 int frame_index, |
| 1351 bool is_setter_stub_frame) { | 1391 bool is_setter_stub_frame) { |
| 1352 JSFunction* accessor = JSFunction::cast(ComputeLiteral(iterator->Next())); | 1392 JSFunction* accessor = JSFunction::cast(ComputeLiteral(iterator->Next())); |
| 1353 // The receiver (and the implicit return value, if any) are expected in | 1393 // The receiver (and the implicit return value, if any) are expected in |
| 1354 // registers by the LoadIC/StoreIC, so they don't belong to the output stack | 1394 // registers by the LoadIC/StoreIC, so they don't belong to the output stack |
| 1355 // frame. This means that we have to use a height of 0. | 1395 // frame. This means that we have to use a height of 0. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1407 intptr_t fp_value = top_address + output_offset; | 1447 intptr_t fp_value = top_address + output_offset; |
| 1408 output_frame->SetFp(fp_value); | 1448 output_frame->SetFp(fp_value); |
| 1409 if (trace_scope_ != NULL) { | 1449 if (trace_scope_ != NULL) { |
| 1410 PrintF(trace_scope_->file(), | 1450 PrintF(trace_scope_->file(), |
| 1411 " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR | 1451 " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR |
| 1412 " ; caller's fp\n", | 1452 " ; caller's fp\n", |
| 1413 fp_value, output_offset, value); | 1453 fp_value, output_offset, value); |
| 1414 } | 1454 } |
| 1415 | 1455 |
| 1416 if (FLAG_enable_ool_constant_pool) { | 1456 if (FLAG_enable_ool_constant_pool) { |
| 1417 // The constant pool pointer can be gotten from the previous frame. | 1457 // Read the caller's constant pool from the previous frame. |
| 1418 output_offset -= kPointerSize; | 1458 output_offset -= kPointerSize; |
| 1419 value = output_[frame_index - 1]->GetConstantPool(); | 1459 value = output_[frame_index - 1]->GetConstantPool(); |
| 1420 output_frame->SetFrameSlot(output_offset, value); | 1460 output_frame->SetCallerConstantPool(output_offset, value); |
| 1421 if (trace_scope_) { | 1461 if (trace_scope_) { |
| 1422 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1462 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 1423 V8PRIxPTR " ; constant pool\n", | 1463 V8PRIxPTR " ; caller's constant pool\n", |
| 1424 top_address + output_offset, output_offset, value); | 1464 top_address + output_offset, output_offset, value); |
| 1425 } | 1465 } |
| 1426 } | 1466 } |
| 1427 | 1467 |
| 1428 // The context can be gotten from the previous frame. | 1468 // The context can be gotten from the previous frame. |
| 1429 output_offset -= kPointerSize; | 1469 output_offset -= kPointerSize; |
| 1430 value = output_[frame_index - 1]->GetContext(); | 1470 value = output_[frame_index - 1]->GetContext(); |
| 1431 output_frame->SetFrameSlot(output_offset, value); | 1471 output_frame->SetFrameSlot(output_offset, value); |
| 1432 if (trace_scope_ != NULL) { | 1472 if (trace_scope_ != NULL) { |
| 1433 PrintF(trace_scope_->file(), | 1473 PrintF(trace_scope_->file(), |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1475 } | 1515 } |
| 1476 | 1516 |
| 1477 ASSERT(0 == output_offset); | 1517 ASSERT(0 == output_offset); |
| 1478 | 1518 |
| 1479 Smi* offset = is_setter_stub_frame ? | 1519 Smi* offset = is_setter_stub_frame ? |
| 1480 isolate_->heap()->setter_stub_deopt_pc_offset() : | 1520 isolate_->heap()->setter_stub_deopt_pc_offset() : |
| 1481 isolate_->heap()->getter_stub_deopt_pc_offset(); | 1521 isolate_->heap()->getter_stub_deopt_pc_offset(); |
| 1482 intptr_t pc = reinterpret_cast<intptr_t>( | 1522 intptr_t pc = reinterpret_cast<intptr_t>( |
| 1483 accessor_stub->instruction_start() + offset->value()); | 1523 accessor_stub->instruction_start() + offset->value()); |
| 1484 output_frame->SetPc(pc); | 1524 output_frame->SetPc(pc); |
| 1525 if (FLAG_enable_ool_constant_pool) { |
| 1526 intptr_t constant_pool_value = |
| 1527 reinterpret_cast<intptr_t>(accessor_stub->constant_pool()); |
| 1528 output_frame->SetConstantPool(constant_pool_value); |
| 1529 } |
| 1485 } | 1530 } |
| 1486 | 1531 |
| 1487 | 1532 |
| 1488 void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator, | 1533 void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator, |
| 1489 int frame_index) { | 1534 int frame_index) { |
| 1490 // | 1535 // |
| 1491 // FROM TO | 1536 // FROM TO |
| 1492 // | .... | | .... | | 1537 // | .... | | .... | |
| 1493 // +-------------------------+ +-------------------------+ | 1538 // +-------------------------+ +-------------------------+ |
| 1494 // | JSFunction continuation | | JSFunction continuation | | 1539 // | JSFunction continuation | | JSFunction continuation | |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1578 output_frame->SetRegister(fp_reg.code(), frame_ptr); | 1623 output_frame->SetRegister(fp_reg.code(), frame_ptr); |
| 1579 output_frame->SetFp(frame_ptr); | 1624 output_frame->SetFp(frame_ptr); |
| 1580 if (trace_scope_ != NULL) { | 1625 if (trace_scope_ != NULL) { |
| 1581 PrintF(trace_scope_->file(), | 1626 PrintF(trace_scope_->file(), |
| 1582 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1627 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 1583 V8PRIxPTR " ; caller's fp\n", | 1628 V8PRIxPTR " ; caller's fp\n", |
| 1584 top_address + output_frame_offset, output_frame_offset, value); | 1629 top_address + output_frame_offset, output_frame_offset, value); |
| 1585 } | 1630 } |
| 1586 | 1631 |
| 1587 if (FLAG_enable_ool_constant_pool) { | 1632 if (FLAG_enable_ool_constant_pool) { |
| 1588 // The constant pool pointer can be gotten from the input frame. | 1633 // Read the caller's constant pool from the input frame. |
| 1589 Register constant_pool_pointer_register = | |
| 1590 StubFailureTrampolineFrame::constant_pool_pointer_register(); | |
| 1591 input_frame_offset -= kPointerSize; | 1634 input_frame_offset -= kPointerSize; |
| 1592 value = input_->GetFrameSlot(input_frame_offset); | 1635 value = input_->GetFrameSlot(input_frame_offset); |
| 1593 output_frame->SetRegister(constant_pool_pointer_register.code(), value); | |
| 1594 output_frame_offset -= kPointerSize; | 1636 output_frame_offset -= kPointerSize; |
| 1595 output_frame->SetFrameSlot(output_frame_offset, value); | 1637 output_frame->SetCallerConstantPool(output_frame_offset, value); |
| 1596 if (trace_scope_) { | 1638 if (trace_scope_) { |
| 1597 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1639 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 1598 V8PRIxPTR " ; constant_pool_pointer\n", | 1640 V8PRIxPTR " ; caller's constant_pool\n", |
| 1599 top_address + output_frame_offset, output_frame_offset, value); | 1641 top_address + output_frame_offset, output_frame_offset, value); |
| 1600 } | 1642 } |
| 1601 } | 1643 } |
| 1602 | 1644 |
| 1603 // The context can be gotten from the input frame. | 1645 // The context can be gotten from the input frame. |
| 1604 Register context_reg = StubFailureTrampolineFrame::context_register(); | 1646 Register context_reg = StubFailureTrampolineFrame::context_register(); |
| 1605 input_frame_offset -= kPointerSize; | 1647 input_frame_offset -= kPointerSize; |
| 1606 value = input_->GetFrameSlot(input_frame_offset); | 1648 value = input_->GetFrameSlot(input_frame_offset); |
| 1607 output_frame->SetRegister(context_reg.code(), value); | 1649 output_frame->SetRegister(context_reg.code(), value); |
| 1608 output_frame_offset -= kPointerSize; | 1650 output_frame_offset -= kPointerSize; |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1722 SetPlatformCompiledStubRegisters(output_frame, descriptor); | 1764 SetPlatformCompiledStubRegisters(output_frame, descriptor); |
| 1723 | 1765 |
| 1724 // Compute this frame's PC, state, and continuation. | 1766 // Compute this frame's PC, state, and continuation. |
| 1725 Code* trampoline = NULL; | 1767 Code* trampoline = NULL; |
| 1726 StubFunctionMode function_mode = descriptor->function_mode_; | 1768 StubFunctionMode function_mode = descriptor->function_mode_; |
| 1727 StubFailureTrampolineStub(function_mode).FindCodeInCache(&trampoline, | 1769 StubFailureTrampolineStub(function_mode).FindCodeInCache(&trampoline, |
| 1728 isolate_); | 1770 isolate_); |
| 1729 ASSERT(trampoline != NULL); | 1771 ASSERT(trampoline != NULL); |
| 1730 output_frame->SetPc(reinterpret_cast<intptr_t>( | 1772 output_frame->SetPc(reinterpret_cast<intptr_t>( |
| 1731 trampoline->instruction_start())); | 1773 trampoline->instruction_start())); |
| 1774 if (FLAG_enable_ool_constant_pool) { |
| 1775 Register constant_pool_reg = |
| 1776 StubFailureTrampolineFrame::constant_pool_pointer_register(); |
| 1777 intptr_t constant_pool_value = |
| 1778 reinterpret_cast<intptr_t>(trampoline->constant_pool()); |
| 1779 output_frame->SetConstantPool(constant_pool_value); |
| 1780 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); |
| 1781 } |
| 1732 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); | 1782 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); |
| 1733 Code* notify_failure = NotifyStubFailureBuiltin(); | 1783 Code* notify_failure = NotifyStubFailureBuiltin(); |
| 1734 output_frame->SetContinuation( | 1784 output_frame->SetContinuation( |
| 1735 reinterpret_cast<intptr_t>(notify_failure->entry())); | 1785 reinterpret_cast<intptr_t>(notify_failure->entry())); |
| 1736 } | 1786 } |
| 1737 | 1787 |
| 1738 | 1788 |
| 1739 Handle<Object> Deoptimizer::MaterializeNextHeapObject() { | 1789 Handle<Object> Deoptimizer::MaterializeNextHeapObject() { |
| 1740 int object_index = materialization_object_index_++; | 1790 int object_index = materialization_object_index_++; |
| 1741 ObjectMaterializationDescriptor desc = deferred_objects_[object_index]; | 1791 ObjectMaterializationDescriptor desc = deferred_objects_[object_index]; |
| 1742 const int length = desc.object_length(); | 1792 const int length = desc.object_length(); |
| 1743 | 1793 |
| 1744 if (desc.duplicate_object() >= 0) { | 1794 if (desc.duplicate_object() >= 0) { |
| 1745 // Found a previously materialized object by de-duplication. | 1795 // Found a previously materialized object by de-duplication. |
| 1746 object_index = desc.duplicate_object(); | 1796 object_index = desc.duplicate_object(); |
| 1747 materialized_objects_->Add(Handle<Object>()); | 1797 materialized_objects_->Add(Handle<Object>()); |
| 1748 } else if (desc.is_arguments() && ArgumentsObjectIsAdapted(object_index)) { | 1798 } else if (desc.is_arguments() && ArgumentsObjectIsAdapted(object_index)) { |
| 1749 // Use the arguments adapter frame we just built to materialize the | 1799 // Use the arguments adapter frame we just built to materialize the |
| 1750 // arguments object. FunctionGetArguments can't throw an exception. | 1800 // arguments object. FunctionGetArguments can't throw an exception. |
| 1751 Handle<JSFunction> function = ArgumentsObjectFunction(object_index); | 1801 Handle<JSFunction> function = ArgumentsObjectFunction(object_index); |
| 1752 Handle<JSObject> arguments = Handle<JSObject>::cast( | 1802 Handle<JSObject> arguments = Handle<JSObject>::cast( |
| 1753 Accessors::FunctionGetArguments(function)); | 1803 Accessors::FunctionGetArguments(function)); |
| 1754 materialized_objects_->Add(arguments); | 1804 materialized_objects_->Add(arguments); |
| 1755 materialization_value_index_ += length; | 1805 // To keep consistent object counters, we still materialize the |
| 1806 // nested values (but we throw them away). |
| 1807 for (int i = 0; i < length; ++i) { |
| 1808 MaterializeNextValue(); |
| 1809 } |
| 1756 } else if (desc.is_arguments()) { | 1810 } else if (desc.is_arguments()) { |
| 1757 // Construct an arguments object and copy the parameters to a newly | 1811 // Construct an arguments object and copy the parameters to a newly |
| 1758 // allocated arguments object backing store. | 1812 // allocated arguments object backing store. |
| 1759 Handle<JSFunction> function = ArgumentsObjectFunction(object_index); | 1813 Handle<JSFunction> function = ArgumentsObjectFunction(object_index); |
| 1760 Handle<JSObject> arguments = | 1814 Handle<JSObject> arguments = |
| 1761 isolate_->factory()->NewArgumentsObject(function, length); | 1815 isolate_->factory()->NewArgumentsObject(function, length); |
| 1762 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length); | 1816 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length); |
| 1763 ASSERT(array->length() == length); | 1817 ASSERT(array->length() == length); |
| 1764 arguments->set_elements(*array); | 1818 arguments->set_elements(*array); |
| 1765 materialized_objects_->Add(arguments); | 1819 materialized_objects_->Add(arguments); |
| (...skipping 1510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3276 Handle<Map>::cast(map_object), Representation::Tagged()); | 3330 Handle<Map>::cast(map_object), Representation::Tagged()); |
| 3277 current_slot_++; | 3331 current_slot_++; |
| 3278 // TODO(jarin) this should be unified with the code in | 3332 // TODO(jarin) this should be unified with the code in |
| 3279 // Deoptimizer::MaterializeNextHeapObject() | 3333 // Deoptimizer::MaterializeNextHeapObject() |
| 3280 switch (map->instance_type()) { | 3334 switch (map->instance_type()) { |
| 3281 case HEAP_NUMBER_TYPE: { | 3335 case HEAP_NUMBER_TYPE: { |
| 3282 // Reuse the HeapNumber value directly as it is already properly | 3336 // Reuse the HeapNumber value directly as it is already properly |
| 3283 // tagged and skip materializing the HeapNumber explicitly. | 3337 // tagged and skip materializing the HeapNumber explicitly. |
| 3284 Handle<Object> object = GetNext(isolate, lvl + 1); | 3338 Handle<Object> object = GetNext(isolate, lvl + 1); |
| 3285 materialized_objects_.Add(object); | 3339 materialized_objects_.Add(object); |
| 3340 // On 32-bit architectures, there is an extra slot there because |
| 3341 // the escape analysis calculates the number of slots as |
| 3342 // object-size/pointer-size. To account for this, we read out |
| 3343 // any extra slots. |
| 3344 for (int i = 0; i < length - 2; i++) { |
| 3345 GetNext(isolate, lvl + 1); |
| 3346 } |
| 3286 return object; | 3347 return object; |
| 3287 } | 3348 } |
| 3288 case JS_OBJECT_TYPE: { | 3349 case JS_OBJECT_TYPE: { |
| 3289 Handle<JSObject> object = | 3350 Handle<JSObject> object = |
| 3290 isolate->factory()->NewJSObjectFromMap(map, NOT_TENURED, false); | 3351 isolate->factory()->NewJSObjectFromMap(map, NOT_TENURED, false); |
| 3291 materialized_objects_.Add(object); | 3352 materialized_objects_.Add(object); |
| 3292 Handle<Object> properties = GetNext(isolate, lvl + 1); | 3353 Handle<Object> properties = GetNext(isolate, lvl + 1); |
| 3293 Handle<Object> elements = GetNext(isolate, lvl + 1); | 3354 Handle<Object> elements = GetNext(isolate, lvl + 1); |
| 3294 object->set_properties(FixedArray::cast(*properties)); | 3355 object->set_properties(FixedArray::cast(*properties)); |
| 3295 object->set_elements(FixedArrayBase::cast(*elements)); | 3356 object->set_elements(FixedArrayBase::cast(*elements)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3330 UNREACHABLE(); | 3391 UNREACHABLE(); |
| 3331 break; | 3392 break; |
| 3332 } | 3393 } |
| 3333 | 3394 |
| 3334 FATAL("We should never get here - unexpected deopt slot kind."); | 3395 FATAL("We should never get here - unexpected deopt slot kind."); |
| 3335 return Handle<Object>::null(); | 3396 return Handle<Object>::null(); |
| 3336 } | 3397 } |
| 3337 | 3398 |
| 3338 | 3399 |
| 3339 void SlotRefValueBuilder::Finish(Isolate* isolate) { | 3400 void SlotRefValueBuilder::Finish(Isolate* isolate) { |
| 3340 // We should have processed all slot | 3401 // We should have processed all the slots |
| 3341 ASSERT(slot_refs_.length() == current_slot_); | 3402 ASSERT(slot_refs_.length() == current_slot_); |
| 3342 | 3403 |
| 3343 if (materialized_objects_.length() > prev_materialized_count_) { | 3404 if (materialized_objects_.length() > prev_materialized_count_) { |
| 3344 // We have materialized some new objects, so we have to store them | 3405 // We have materialized some new objects, so we have to store them |
| 3345 // to prevent duplicate materialization | 3406 // to prevent duplicate materialization |
| 3346 Handle<FixedArray> array = isolate->factory()->NewFixedArray( | 3407 Handle<FixedArray> array = isolate->factory()->NewFixedArray( |
| 3347 materialized_objects_.length()); | 3408 materialized_objects_.length()); |
| 3348 for (int i = 0; i < materialized_objects_.length(); i++) { | 3409 for (int i = 0; i < materialized_objects_.length(); i++) { |
| 3349 array->set(i, *(materialized_objects_.at(i))); | 3410 array->set(i, *(materialized_objects_.at(i))); |
| 3350 } | 3411 } |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3471 | 3532 |
| 3472 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | 3533 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
| 3473 v->VisitPointer(BitCast<Object**>(&function_)); | 3534 v->VisitPointer(BitCast<Object**>(&function_)); |
| 3474 v->VisitPointers(parameters_, parameters_ + parameters_count_); | 3535 v->VisitPointers(parameters_, parameters_ + parameters_count_); |
| 3475 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | 3536 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
| 3476 } | 3537 } |
| 3477 | 3538 |
| 3478 #endif // ENABLE_DEBUGGER_SUPPORT | 3539 #endif // ENABLE_DEBUGGER_SUPPORT |
| 3479 | 3540 |
| 3480 } } // namespace v8::internal | 3541 } } // namespace v8::internal |
| OLD | NEW |