| 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 } | 80 } |
| 81 | 81 |
| 82 | 82 |
| 83 Code* Deoptimizer::FindDeoptimizingCode(Address addr) { | 83 Code* Deoptimizer::FindDeoptimizingCode(Address addr) { |
| 84 if (function_->IsHeapObject()) { | 84 if (function_->IsHeapObject()) { |
| 85 // Search all deoptimizing code in the native context of the function. | 85 // Search all deoptimizing code in the native context of the function. |
| 86 Context* native_context = function_->context()->native_context(); | 86 Context* native_context = function_->context()->native_context(); |
| 87 Object* element = native_context->DeoptimizedCodeListHead(); | 87 Object* element = native_context->DeoptimizedCodeListHead(); |
| 88 while (!element->IsUndefined()) { | 88 while (!element->IsUndefined()) { |
| 89 Code* code = Code::cast(element); | 89 Code* code = Code::cast(element); |
| 90 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); | 90 CHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
| 91 if (code->contains(addr)) return code; | 91 if (code->contains(addr)) return code; |
| 92 element = code->next_code_link(); | 92 element = code->next_code_link(); |
| 93 } | 93 } |
| 94 } | 94 } |
| 95 return NULL; | 95 return NULL; |
| 96 } | 96 } |
| 97 | 97 |
| 98 | 98 |
| 99 // We rely on this function not causing a GC. It is called from generated code | 99 // We rely on this function not causing a GC. It is called from generated code |
| 100 // without having a real stack frame in place. | 100 // without having a real stack frame in place. |
| 101 Deoptimizer* Deoptimizer::New(JSFunction* function, | 101 Deoptimizer* Deoptimizer::New(JSFunction* function, |
| 102 BailoutType type, | 102 BailoutType type, |
| 103 unsigned bailout_id, | 103 unsigned bailout_id, |
| 104 Address from, | 104 Address from, |
| 105 int fp_to_sp_delta, | 105 int fp_to_sp_delta, |
| 106 Isolate* isolate) { | 106 Isolate* isolate) { |
| 107 Deoptimizer* deoptimizer = new Deoptimizer(isolate, | 107 Deoptimizer* deoptimizer = new Deoptimizer(isolate, |
| 108 function, | 108 function, |
| 109 type, | 109 type, |
| 110 bailout_id, | 110 bailout_id, |
| 111 from, | 111 from, |
| 112 fp_to_sp_delta, | 112 fp_to_sp_delta, |
| 113 NULL); | 113 NULL); |
| 114 ASSERT(isolate->deoptimizer_data()->current_ == NULL); | 114 CHECK(isolate->deoptimizer_data()->current_ == NULL); |
| 115 isolate->deoptimizer_data()->current_ = deoptimizer; | 115 isolate->deoptimizer_data()->current_ = deoptimizer; |
| 116 return deoptimizer; | 116 return deoptimizer; |
| 117 } | 117 } |
| 118 | 118 |
| 119 | 119 |
| 120 // No larger than 2K on all platforms | 120 // No larger than 2K on all platforms |
| 121 static const int kDeoptTableMaxEpilogueCodeSize = 2 * KB; | 121 static const int kDeoptTableMaxEpilogueCodeSize = 2 * KB; |
| 122 | 122 |
| 123 | 123 |
| 124 size_t Deoptimizer::GetMaxDeoptTableSize() { | 124 size_t Deoptimizer::GetMaxDeoptTableSize() { |
| 125 int entries_size = | 125 int entries_size = |
| 126 Deoptimizer::kMaxNumberOfEntries * Deoptimizer::table_entry_size_; | 126 Deoptimizer::kMaxNumberOfEntries * Deoptimizer::table_entry_size_; |
| 127 int commit_page_size = static_cast<int>(OS::CommitPageSize()); | 127 int commit_page_size = static_cast<int>(OS::CommitPageSize()); |
| 128 int page_count = ((kDeoptTableMaxEpilogueCodeSize + entries_size - 1) / | 128 int page_count = ((kDeoptTableMaxEpilogueCodeSize + entries_size - 1) / |
| 129 commit_page_size) + 1; | 129 commit_page_size) + 1; |
| 130 return static_cast<size_t>(commit_page_size * page_count); | 130 return static_cast<size_t>(commit_page_size * page_count); |
| 131 } | 131 } |
| 132 | 132 |
| 133 | 133 |
| 134 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { | 134 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { |
| 135 Deoptimizer* result = isolate->deoptimizer_data()->current_; | 135 Deoptimizer* result = isolate->deoptimizer_data()->current_; |
| 136 ASSERT(result != NULL); | 136 CHECK_NE(result, NULL); |
| 137 result->DeleteFrameDescriptions(); | 137 result->DeleteFrameDescriptions(); |
| 138 isolate->deoptimizer_data()->current_ = NULL; | 138 isolate->deoptimizer_data()->current_ = NULL; |
| 139 return result; | 139 return result; |
| 140 } | 140 } |
| 141 | 141 |
| 142 | 142 |
| 143 int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) { | 143 int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) { |
| 144 if (jsframe_index == 0) return 0; | 144 if (jsframe_index == 0) return 0; |
| 145 | 145 |
| 146 int frame_index = 0; | 146 int frame_index = 0; |
| 147 while (jsframe_index >= 0) { | 147 while (jsframe_index >= 0) { |
| 148 FrameDescription* frame = output_[frame_index]; | 148 FrameDescription* frame = output_[frame_index]; |
| 149 if (frame->GetFrameType() == StackFrame::JAVA_SCRIPT) { | 149 if (frame->GetFrameType() == StackFrame::JAVA_SCRIPT) { |
| 150 jsframe_index--; | 150 jsframe_index--; |
| 151 } | 151 } |
| 152 frame_index++; | 152 frame_index++; |
| 153 } | 153 } |
| 154 | 154 |
| 155 return frame_index - 1; | 155 return frame_index - 1; |
| 156 } | 156 } |
| 157 | 157 |
| 158 | 158 |
| 159 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( | 159 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( |
| 160 JavaScriptFrame* frame, | 160 JavaScriptFrame* frame, |
| 161 int jsframe_index, | 161 int jsframe_index, |
| 162 Isolate* isolate) { | 162 Isolate* isolate) { |
| 163 ASSERT(frame->is_optimized()); | 163 CHECK(frame->is_optimized()); |
| 164 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL); | 164 CHECK(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL); |
| 165 | 165 |
| 166 // Get the function and code from the frame. | 166 // Get the function and code from the frame. |
| 167 JSFunction* function = frame->function(); | 167 JSFunction* function = frame->function(); |
| 168 Code* code = frame->LookupCode(); | 168 Code* code = frame->LookupCode(); |
| 169 | 169 |
| 170 // Locate the deoptimization point in the code. As we are at a call the | 170 // Locate the deoptimization point in the code. As we are at a call the |
| 171 // return address must be at a place in the code with deoptimization support. | 171 // return address must be at a place in the code with deoptimization support. |
| 172 SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc()); | 172 SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc()); |
| 173 int deoptimization_index = safepoint_entry.deoptimization_index(); | 173 int deoptimization_index = safepoint_entry.deoptimization_index(); |
| 174 ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex); | 174 CHECK_NE(deoptimization_index, Safepoint::kNoDeoptimizationIndex); |
| 175 | 175 |
| 176 // Always use the actual stack slots when calculating the fp to sp | 176 // Always use the actual stack slots when calculating the fp to sp |
| 177 // delta adding two for the function and context. | 177 // delta adding two for the function and context. |
| 178 unsigned stack_slots = code->stack_slots(); | 178 unsigned stack_slots = code->stack_slots(); |
| 179 unsigned fp_to_sp_delta = (stack_slots * kPointerSize) + | 179 unsigned fp_to_sp_delta = (stack_slots * kPointerSize) + |
| 180 StandardFrameConstants::kFixedFrameSizeFromFp; | 180 StandardFrameConstants::kFixedFrameSizeFromFp; |
| 181 | 181 |
| 182 Deoptimizer* deoptimizer = new Deoptimizer(isolate, | 182 Deoptimizer* deoptimizer = new Deoptimizer(isolate, |
| 183 function, | 183 function, |
| 184 Deoptimizer::DEBUGGER, | 184 Deoptimizer::DEBUGGER, |
| 185 deoptimization_index, | 185 deoptimization_index, |
| 186 frame->pc(), | 186 frame->pc(), |
| 187 fp_to_sp_delta, | 187 fp_to_sp_delta, |
| 188 code); | 188 code); |
| 189 Address tos = frame->fp() - fp_to_sp_delta; | 189 Address tos = frame->fp() - fp_to_sp_delta; |
| 190 deoptimizer->FillInputFrame(tos, frame); | 190 deoptimizer->FillInputFrame(tos, frame); |
| 191 | 191 |
| 192 // Calculate the output frames. | 192 // Calculate the output frames. |
| 193 Deoptimizer::ComputeOutputFrames(deoptimizer); | 193 Deoptimizer::ComputeOutputFrames(deoptimizer); |
| 194 | 194 |
| 195 // Create the GC safe output frame information and register it for GC | 195 // Create the GC safe output frame information and register it for GC |
| 196 // handling. | 196 // handling. |
| 197 ASSERT_LT(jsframe_index, deoptimizer->jsframe_count()); | 197 CHECK_LT(jsframe_index, deoptimizer->jsframe_count()); |
| 198 | 198 |
| 199 // Convert JS frame index into frame index. | 199 // Convert JS frame index into frame index. |
| 200 int frame_index = deoptimizer->ConvertJSFrameIndexToFrameIndex(jsframe_index); | 200 int frame_index = deoptimizer->ConvertJSFrameIndexToFrameIndex(jsframe_index); |
| 201 | 201 |
| 202 bool has_arguments_adaptor = | 202 bool has_arguments_adaptor = |
| 203 frame_index > 0 && | 203 frame_index > 0 && |
| 204 deoptimizer->output_[frame_index - 1]->GetFrameType() == | 204 deoptimizer->output_[frame_index - 1]->GetFrameType() == |
| 205 StackFrame::ARGUMENTS_ADAPTOR; | 205 StackFrame::ARGUMENTS_ADAPTOR; |
| 206 | 206 |
| 207 int construct_offset = has_arguments_adaptor ? 2 : 1; | 207 int construct_offset = has_arguments_adaptor ? 2 : 1; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 | 239 |
| 240 // Finished using the deoptimizer instance. | 240 // Finished using the deoptimizer instance. |
| 241 delete deoptimizer; | 241 delete deoptimizer; |
| 242 | 242 |
| 243 return info; | 243 return info; |
| 244 } | 244 } |
| 245 | 245 |
| 246 | 246 |
| 247 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, | 247 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, |
| 248 Isolate* isolate) { | 248 Isolate* isolate) { |
| 249 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == info); | 249 CHECK_EQ(isolate->deoptimizer_data()->deoptimized_frame_info_, info); |
| 250 delete info; | 250 delete info; |
| 251 isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL; | 251 isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL; |
| 252 } | 252 } |
| 253 | 253 |
| 254 | 254 |
| 255 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, | 255 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, |
| 256 int count, | 256 int count, |
| 257 BailoutType type) { | 257 BailoutType type) { |
| 258 TableEntryGenerator generator(masm, type, count); | 258 TableEntryGenerator generator(masm, type, count); |
| 259 generator.Generate(); | 259 generator.Generate(); |
| 260 } | 260 } |
| 261 | 261 |
| 262 | 262 |
| 263 void Deoptimizer::VisitAllOptimizedFunctionsForContext( | 263 void Deoptimizer::VisitAllOptimizedFunctionsForContext( |
| 264 Context* context, OptimizedFunctionVisitor* visitor) { | 264 Context* context, OptimizedFunctionVisitor* visitor) { |
| 265 DisallowHeapAllocation no_allocation; | 265 DisallowHeapAllocation no_allocation; |
| 266 | 266 |
| 267 ASSERT(context->IsNativeContext()); | 267 CHECK(context->IsNativeContext()); |
| 268 | 268 |
| 269 visitor->EnterContext(context); | 269 visitor->EnterContext(context); |
| 270 | 270 |
| 271 // Visit the list of optimized functions, removing elements that | 271 // Visit the list of optimized functions, removing elements that |
| 272 // no longer refer to optimized code. | 272 // no longer refer to optimized code. |
| 273 JSFunction* prev = NULL; | 273 JSFunction* prev = NULL; |
| 274 Object* element = context->OptimizedFunctionsListHead(); | 274 Object* element = context->OptimizedFunctionsListHead(); |
| 275 while (!element->IsUndefined()) { | 275 while (!element->IsUndefined()) { |
| 276 JSFunction* function = JSFunction::cast(element); | 276 JSFunction* function = JSFunction::cast(element); |
| 277 Object* next = function->next_function_link(); | 277 Object* next = function->next_function_link(); |
| 278 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION || | 278 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION || |
| 279 (visitor->VisitFunction(function), | 279 (visitor->VisitFunction(function), |
| 280 function->code()->kind() != Code::OPTIMIZED_FUNCTION)) { | 280 function->code()->kind() != Code::OPTIMIZED_FUNCTION)) { |
| 281 // The function no longer refers to optimized code, or the visitor | 281 // The function no longer refers to optimized code, or the visitor |
| 282 // changed the code to which it refers to no longer be optimized code. | 282 // changed the code to which it refers to no longer be optimized code. |
| 283 // Remove the function from this list. | 283 // Remove the function from this list. |
| 284 if (prev != NULL) { | 284 if (prev != NULL) { |
| 285 prev->set_next_function_link(next); | 285 prev->set_next_function_link(next); |
| 286 } else { | 286 } else { |
| 287 context->SetOptimizedFunctionsListHead(next); | 287 context->SetOptimizedFunctionsListHead(next); |
| 288 } | 288 } |
| 289 // The visitor should not alter the link directly. | 289 // The visitor should not alter the link directly. |
| 290 ASSERT(function->next_function_link() == next); | 290 CHECK_EQ(function->next_function_link(), next); |
| 291 // Set the next function link to undefined to indicate it is no longer | 291 // Set the next function link to undefined to indicate it is no longer |
| 292 // in the optimized functions list. | 292 // in the optimized functions list. |
| 293 function->set_next_function_link(context->GetHeap()->undefined_value()); | 293 function->set_next_function_link(context->GetHeap()->undefined_value()); |
| 294 } else { | 294 } else { |
| 295 // The visitor should not alter the link directly. | 295 // The visitor should not alter the link directly. |
| 296 ASSERT(function->next_function_link() == next); | 296 CHECK_EQ(function->next_function_link(), next); |
| 297 // preserve this element. | 297 // preserve this element. |
| 298 prev = function; | 298 prev = function; |
| 299 } | 299 } |
| 300 element = next; | 300 element = next; |
| 301 } | 301 } |
| 302 | 302 |
| 303 visitor->LeaveContext(context); | 303 visitor->LeaveContext(context); |
| 304 } | 304 } |
| 305 | 305 |
| 306 | 306 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 // Move marked code from the optimized code list to the deoptimized | 388 // Move marked code from the optimized code list to the deoptimized |
| 389 // code list, collecting them into a ZoneList. | 389 // code list, collecting them into a ZoneList. |
| 390 Zone zone(isolate); | 390 Zone zone(isolate); |
| 391 ZoneList<Code*> codes(10, &zone); | 391 ZoneList<Code*> codes(10, &zone); |
| 392 | 392 |
| 393 // Walk over all optimized code objects in this native context. | 393 // Walk over all optimized code objects in this native context. |
| 394 Code* prev = NULL; | 394 Code* prev = NULL; |
| 395 Object* element = context->OptimizedCodeListHead(); | 395 Object* element = context->OptimizedCodeListHead(); |
| 396 while (!element->IsUndefined()) { | 396 while (!element->IsUndefined()) { |
| 397 Code* code = Code::cast(element); | 397 Code* code = Code::cast(element); |
| 398 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); | 398 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION); |
| 399 Object* next = code->next_code_link(); | 399 Object* next = code->next_code_link(); |
| 400 if (code->marked_for_deoptimization()) { | 400 if (code->marked_for_deoptimization()) { |
| 401 // Put the code into the list for later patching. | 401 // Put the code into the list for later patching. |
| 402 codes.Add(code, &zone); | 402 codes.Add(code, &zone); |
| 403 | 403 |
| 404 if (prev != NULL) { | 404 if (prev != NULL) { |
| 405 // Skip this code in the optimized code list. | 405 // Skip this code in the optimized code list. |
| 406 prev->set_next_code_link(next); | 406 prev->set_next_code_link(next); |
| 407 } else { | 407 } else { |
| 408 // There was no previous node, the next node is the new head. | 408 // There was no previous node, the next node is the new head. |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 | 476 |
| 477 | 477 |
| 478 void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) { | 478 void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) { |
| 479 if (FLAG_trace_deopt) { | 479 if (FLAG_trace_deopt) { |
| 480 CodeTracer::Scope scope(object->GetHeap()->isolate()->GetCodeTracer()); | 480 CodeTracer::Scope scope(object->GetHeap()->isolate()->GetCodeTracer()); |
| 481 PrintF(scope.file(), "[deoptimize global object @ 0x%08" V8PRIxPTR "]\n", | 481 PrintF(scope.file(), "[deoptimize global object @ 0x%08" V8PRIxPTR "]\n", |
| 482 reinterpret_cast<intptr_t>(object)); | 482 reinterpret_cast<intptr_t>(object)); |
| 483 } | 483 } |
| 484 if (object->IsJSGlobalProxy()) { | 484 if (object->IsJSGlobalProxy()) { |
| 485 Object* proto = object->GetPrototype(); | 485 Object* proto = object->GetPrototype(); |
| 486 ASSERT(proto->IsJSGlobalObject()); | 486 CHECK(proto->IsJSGlobalObject()); |
| 487 Context* native_context = GlobalObject::cast(proto)->native_context(); | 487 Context* native_context = GlobalObject::cast(proto)->native_context(); |
| 488 MarkAllCodeForContext(native_context); | 488 MarkAllCodeForContext(native_context); |
| 489 DeoptimizeMarkedCodeForContext(native_context); | 489 DeoptimizeMarkedCodeForContext(native_context); |
| 490 } else if (object->IsGlobalObject()) { | 490 } else if (object->IsGlobalObject()) { |
| 491 Context* native_context = GlobalObject::cast(object)->native_context(); | 491 Context* native_context = GlobalObject::cast(object)->native_context(); |
| 492 MarkAllCodeForContext(native_context); | 492 MarkAllCodeForContext(native_context); |
| 493 DeoptimizeMarkedCodeForContext(native_context); | 493 DeoptimizeMarkedCodeForContext(native_context); |
| 494 } | 494 } |
| 495 } | 495 } |
| 496 | 496 |
| 497 | 497 |
| 498 void Deoptimizer::MarkAllCodeForContext(Context* context) { | 498 void Deoptimizer::MarkAllCodeForContext(Context* context) { |
| 499 Object* element = context->OptimizedCodeListHead(); | 499 Object* element = context->OptimizedCodeListHead(); |
| 500 while (!element->IsUndefined()) { | 500 while (!element->IsUndefined()) { |
| 501 Code* code = Code::cast(element); | 501 Code* code = Code::cast(element); |
| 502 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); | 502 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION); |
| 503 code->set_marked_for_deoptimization(true); | 503 code->set_marked_for_deoptimization(true); |
| 504 element = code->next_code_link(); | 504 element = code->next_code_link(); |
| 505 } | 505 } |
| 506 } | 506 } |
| 507 | 507 |
| 508 | 508 |
| 509 void Deoptimizer::DeoptimizeFunction(JSFunction* function) { | 509 void Deoptimizer::DeoptimizeFunction(JSFunction* function) { |
| 510 Code* code = function->code(); | 510 Code* code = function->code(); |
| 511 if (code->kind() == Code::OPTIMIZED_FUNCTION) { | 511 if (code->kind() == Code::OPTIMIZED_FUNCTION) { |
| 512 // Mark the code for deoptimization and unlink any functions that also | 512 // Mark the code for deoptimization and unlink any functions that also |
| (...skipping 14 matching lines...) Expand all Loading... |
| 527 StackFrame::Type frame_type) { | 527 StackFrame::Type frame_type) { |
| 528 switch (deopt_type) { | 528 switch (deopt_type) { |
| 529 case EAGER: | 529 case EAGER: |
| 530 case SOFT: | 530 case SOFT: |
| 531 case LAZY: | 531 case LAZY: |
| 532 case DEBUGGER: | 532 case DEBUGGER: |
| 533 return (frame_type == StackFrame::STUB) | 533 return (frame_type == StackFrame::STUB) |
| 534 ? FLAG_trace_stub_failures | 534 ? FLAG_trace_stub_failures |
| 535 : FLAG_trace_deopt; | 535 : FLAG_trace_deopt; |
| 536 } | 536 } |
| 537 UNREACHABLE(); | 537 FATAL("Unsupported deopt type"); |
| 538 return false; | 538 return false; |
| 539 } | 539 } |
| 540 | 540 |
| 541 | 541 |
| 542 const char* Deoptimizer::MessageFor(BailoutType type) { | 542 const char* Deoptimizer::MessageFor(BailoutType type) { |
| 543 switch (type) { | 543 switch (type) { |
| 544 case EAGER: return "eager"; | 544 case EAGER: return "eager"; |
| 545 case SOFT: return "soft"; | 545 case SOFT: return "soft"; |
| 546 case LAZY: return "lazy"; | 546 case LAZY: return "lazy"; |
| 547 case DEBUGGER: return "debugger"; | 547 case DEBUGGER: return "debugger"; |
| 548 } | 548 } |
| 549 UNREACHABLE(); | 549 FATAL("Unsupported deopt type"); |
| 550 return NULL; | 550 return NULL; |
| 551 } | 551 } |
| 552 | 552 |
| 553 | 553 |
| 554 Deoptimizer::Deoptimizer(Isolate* isolate, | 554 Deoptimizer::Deoptimizer(Isolate* isolate, |
| 555 JSFunction* function, | 555 JSFunction* function, |
| 556 BailoutType type, | 556 BailoutType type, |
| 557 unsigned bailout_id, | 557 unsigned bailout_id, |
| 558 Address from, | 558 Address from, |
| 559 int fp_to_sp_delta, | 559 int fp_to_sp_delta, |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 case Deoptimizer::LAZY: { | 629 case Deoptimizer::LAZY: { |
| 630 Code* compiled_code = FindDeoptimizingCode(from_); | 630 Code* compiled_code = FindDeoptimizingCode(from_); |
| 631 return (compiled_code == NULL) | 631 return (compiled_code == NULL) |
| 632 ? static_cast<Code*>(isolate_->FindCodeObject(from_)) | 632 ? static_cast<Code*>(isolate_->FindCodeObject(from_)) |
| 633 : compiled_code; | 633 : compiled_code; |
| 634 } | 634 } |
| 635 case Deoptimizer::DEBUGGER: | 635 case Deoptimizer::DEBUGGER: |
| 636 ASSERT(optimized_code->contains(from_)); | 636 ASSERT(optimized_code->contains(from_)); |
| 637 return optimized_code; | 637 return optimized_code; |
| 638 } | 638 } |
| 639 UNREACHABLE(); | 639 FATAL("Could not find code for optimized function"); |
| 640 return NULL; | 640 return NULL; |
| 641 } | 641 } |
| 642 | 642 |
| 643 | 643 |
| 644 void Deoptimizer::PrintFunctionName() { | 644 void Deoptimizer::PrintFunctionName() { |
| 645 if (function_->IsJSFunction()) { | 645 if (function_->IsJSFunction()) { |
| 646 function_->PrintName(trace_scope_->file()); | 646 function_->PrintName(trace_scope_->file()); |
| 647 } else { | 647 } else { |
| 648 PrintF(trace_scope_->file(), | 648 PrintF(trace_scope_->file(), |
| 649 "%s", Code::Kind2String(compiled_code_->kind())); | 649 "%s", Code::Kind2String(compiled_code_->kind())); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 672 delete disallow_heap_allocation_; | 672 delete disallow_heap_allocation_; |
| 673 disallow_heap_allocation_ = NULL; | 673 disallow_heap_allocation_ = NULL; |
| 674 #endif // DEBUG | 674 #endif // DEBUG |
| 675 } | 675 } |
| 676 | 676 |
| 677 | 677 |
| 678 Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate, | 678 Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate, |
| 679 int id, | 679 int id, |
| 680 BailoutType type, | 680 BailoutType type, |
| 681 GetEntryMode mode) { | 681 GetEntryMode mode) { |
| 682 ASSERT(id >= 0); | 682 CHECK_GE(id, 0); |
| 683 if (id >= kMaxNumberOfEntries) return NULL; | 683 if (id >= kMaxNumberOfEntries) return NULL; |
| 684 if (mode == ENSURE_ENTRY_CODE) { | 684 if (mode == ENSURE_ENTRY_CODE) { |
| 685 EnsureCodeForDeoptimizationEntry(isolate, type, id); | 685 EnsureCodeForDeoptimizationEntry(isolate, type, id); |
| 686 } else { | 686 } else { |
| 687 ASSERT(mode == CALCULATE_ENTRY_ADDRESS); | 687 CHECK_EQ(mode, CALCULATE_ENTRY_ADDRESS); |
| 688 } | 688 } |
| 689 DeoptimizerData* data = isolate->deoptimizer_data(); | 689 DeoptimizerData* data = isolate->deoptimizer_data(); |
| 690 ASSERT(type < kBailoutTypesWithCodeEntry); | 690 CHECK_LT(type, kBailoutTypesWithCodeEntry); |
| 691 MemoryChunk* base = data->deopt_entry_code_[type]; | 691 MemoryChunk* base = data->deopt_entry_code_[type]; |
| 692 return base->area_start() + (id * table_entry_size_); | 692 return base->area_start() + (id * table_entry_size_); |
| 693 } | 693 } |
| 694 | 694 |
| 695 | 695 |
| 696 int Deoptimizer::GetDeoptimizationId(Isolate* isolate, | 696 int Deoptimizer::GetDeoptimizationId(Isolate* isolate, |
| 697 Address addr, | 697 Address addr, |
| 698 BailoutType type) { | 698 BailoutType type) { |
| 699 DeoptimizerData* data = isolate->deoptimizer_data(); | 699 DeoptimizerData* data = isolate->deoptimizer_data(); |
| 700 MemoryChunk* base = data->deopt_entry_code_[type]; | 700 MemoryChunk* base = data->deopt_entry_code_[type]; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 843 case Translation::INT32_REGISTER: | 843 case Translation::INT32_REGISTER: |
| 844 case Translation::UINT32_REGISTER: | 844 case Translation::UINT32_REGISTER: |
| 845 case Translation::DOUBLE_REGISTER: | 845 case Translation::DOUBLE_REGISTER: |
| 846 case Translation::STACK_SLOT: | 846 case Translation::STACK_SLOT: |
| 847 case Translation::INT32_STACK_SLOT: | 847 case Translation::INT32_STACK_SLOT: |
| 848 case Translation::UINT32_STACK_SLOT: | 848 case Translation::UINT32_STACK_SLOT: |
| 849 case Translation::DOUBLE_STACK_SLOT: | 849 case Translation::DOUBLE_STACK_SLOT: |
| 850 case Translation::LITERAL: | 850 case Translation::LITERAL: |
| 851 case Translation::ARGUMENTS_OBJECT: | 851 case Translation::ARGUMENTS_OBJECT: |
| 852 default: | 852 default: |
| 853 UNREACHABLE(); | 853 FATAL("Unsupported translation"); |
| 854 break; | 854 break; |
| 855 } | 855 } |
| 856 } | 856 } |
| 857 | 857 |
| 858 // Print some helpful diagnostic information. | 858 // Print some helpful diagnostic information. |
| 859 if (trace_scope_ != NULL) { | 859 if (trace_scope_ != NULL) { |
| 860 double ms = timer.Elapsed().InMillisecondsF(); | 860 double ms = timer.Elapsed().InMillisecondsF(); |
| 861 int index = output_count_ - 1; // Index of the topmost frame. | 861 int index = output_count_ - 1; // Index of the topmost frame. |
| 862 JSFunction* function = output_[index]->GetFunction(); | 862 JSFunction* function = output_[index]->GetFunction(); |
| 863 PrintF(trace_scope_->file(), | 863 PrintF(trace_scope_->file(), |
| (...skipping 18 matching lines...) Expand all Loading... |
| 882 | 882 |
| 883 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, | 883 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, |
| 884 int frame_index) { | 884 int frame_index) { |
| 885 BailoutId node_id = BailoutId(iterator->Next()); | 885 BailoutId node_id = BailoutId(iterator->Next()); |
| 886 JSFunction* function; | 886 JSFunction* function; |
| 887 if (frame_index != 0) { | 887 if (frame_index != 0) { |
| 888 function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 888 function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
| 889 } else { | 889 } else { |
| 890 int closure_id = iterator->Next(); | 890 int closure_id = iterator->Next(); |
| 891 USE(closure_id); | 891 USE(closure_id); |
| 892 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); | 892 CHECK_EQ(Translation::kSelfLiteralId, closure_id); |
| 893 function = function_; | 893 function = function_; |
| 894 } | 894 } |
| 895 unsigned height = iterator->Next(); | 895 unsigned height = iterator->Next(); |
| 896 unsigned height_in_bytes = height * kPointerSize; | 896 unsigned height_in_bytes = height * kPointerSize; |
| 897 if (trace_scope_ != NULL) { | 897 if (trace_scope_ != NULL) { |
| 898 PrintF(trace_scope_->file(), " translating "); | 898 PrintF(trace_scope_->file(), " translating "); |
| 899 function->PrintName(trace_scope_->file()); | 899 function->PrintName(trace_scope_->file()); |
| 900 PrintF(trace_scope_->file(), | 900 PrintF(trace_scope_->file(), |
| 901 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); | 901 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); |
| 902 } | 902 } |
| 903 | 903 |
| 904 // The 'fixed' part of the frame consists of the incoming parameters and | 904 // The 'fixed' part of the frame consists of the incoming parameters and |
| 905 // the part described by JavaScriptFrameConstants. | 905 // the part described by JavaScriptFrameConstants. |
| 906 unsigned fixed_frame_size = ComputeFixedSize(function); | 906 unsigned fixed_frame_size = ComputeFixedSize(function); |
| 907 unsigned input_frame_size = input_->GetFrameSize(); | 907 unsigned input_frame_size = input_->GetFrameSize(); |
| 908 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 908 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
| 909 | 909 |
| 910 // Allocate and store the output frame description. | 910 // Allocate and store the output frame description. |
| 911 FrameDescription* output_frame = | 911 FrameDescription* output_frame = |
| 912 new(output_frame_size) FrameDescription(output_frame_size, function); | 912 new(output_frame_size) FrameDescription(output_frame_size, function); |
| 913 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); | 913 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); |
| 914 | 914 |
| 915 bool is_bottommost = (0 == frame_index); | 915 bool is_bottommost = (0 == frame_index); |
| 916 bool is_topmost = (output_count_ - 1 == frame_index); | 916 bool is_topmost = (output_count_ - 1 == frame_index); |
| 917 ASSERT(frame_index >= 0 && frame_index < output_count_); | 917 CHECK(frame_index >= 0 && frame_index < output_count_); |
| 918 ASSERT(output_[frame_index] == NULL); | 918 CHECK_EQ(output_[frame_index], NULL); |
| 919 output_[frame_index] = output_frame; | 919 output_[frame_index] = output_frame; |
| 920 | 920 |
| 921 // The top address for the bottommost output frame can be computed from | 921 // The top address for the bottommost output frame can be computed from |
| 922 // the input frame pointer and the output frame's height. For all | 922 // the input frame pointer and the output frame's height. For all |
| 923 // subsequent output frames, it can be computed from the previous one's | 923 // subsequent output frames, it can be computed from the previous one's |
| 924 // top address and the current frame's size. | 924 // top address and the current frame's size. |
| 925 Register fp_reg = JavaScriptFrame::fp_register(); | 925 Register fp_reg = JavaScriptFrame::fp_register(); |
| 926 intptr_t top_address; | 926 intptr_t top_address; |
| 927 if (is_bottommost) { | 927 if (is_bottommost) { |
| 928 // Determine whether the input frame contains alignment padding. | 928 // Determine whether the input frame contains alignment padding. |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1052 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1052 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 1053 V8PRIxPTR "; function\n", | 1053 V8PRIxPTR "; function\n", |
| 1054 top_address + output_offset, output_offset, value); | 1054 top_address + output_offset, output_offset, value); |
| 1055 } | 1055 } |
| 1056 | 1056 |
| 1057 // Translate the rest of the frame. | 1057 // Translate the rest of the frame. |
| 1058 for (unsigned i = 0; i < height; ++i) { | 1058 for (unsigned i = 0; i < height; ++i) { |
| 1059 output_offset -= kPointerSize; | 1059 output_offset -= kPointerSize; |
| 1060 DoTranslateCommand(iterator, frame_index, output_offset); | 1060 DoTranslateCommand(iterator, frame_index, output_offset); |
| 1061 } | 1061 } |
| 1062 ASSERT(0 == output_offset); | 1062 CHECK_EQ(0, output_offset); |
| 1063 | 1063 |
| 1064 // Compute this frame's PC, state, and continuation. | 1064 // Compute this frame's PC, state, and continuation. |
| 1065 Code* non_optimized_code = function->shared()->code(); | 1065 Code* non_optimized_code = function->shared()->code(); |
| 1066 FixedArray* raw_data = non_optimized_code->deoptimization_data(); | 1066 FixedArray* raw_data = non_optimized_code->deoptimization_data(); |
| 1067 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); | 1067 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); |
| 1068 Address start = non_optimized_code->instruction_start(); | 1068 Address start = non_optimized_code->instruction_start(); |
| 1069 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); | 1069 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); |
| 1070 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); | 1070 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); |
| 1071 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); | 1071 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); |
| 1072 output_frame->SetPc(pc_value); | 1072 output_frame->SetPc(pc_value); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1089 | 1089 |
| 1090 // Set the continuation for the topmost frame. | 1090 // Set the continuation for the topmost frame. |
| 1091 if (is_topmost && bailout_type_ != DEBUGGER) { | 1091 if (is_topmost && bailout_type_ != DEBUGGER) { |
| 1092 Builtins* builtins = isolate_->builtins(); | 1092 Builtins* builtins = isolate_->builtins(); |
| 1093 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); | 1093 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); |
| 1094 if (bailout_type_ == LAZY) { | 1094 if (bailout_type_ == LAZY) { |
| 1095 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); | 1095 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
| 1096 } else if (bailout_type_ == SOFT) { | 1096 } else if (bailout_type_ == SOFT) { |
| 1097 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); | 1097 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); |
| 1098 } else { | 1098 } else { |
| 1099 ASSERT(bailout_type_ == EAGER); | 1099 CHECK_EQ(bailout_type_, EAGER); |
| 1100 } | 1100 } |
| 1101 output_frame->SetContinuation( | 1101 output_frame->SetContinuation( |
| 1102 reinterpret_cast<intptr_t>(continuation->entry())); | 1102 reinterpret_cast<intptr_t>(continuation->entry())); |
| 1103 } | 1103 } |
| 1104 } | 1104 } |
| 1105 | 1105 |
| 1106 | 1106 |
| 1107 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, | 1107 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, |
| 1108 int frame_index) { | 1108 int frame_index) { |
| 1109 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 1109 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
| 1110 unsigned height = iterator->Next(); | 1110 unsigned height = iterator->Next(); |
| 1111 unsigned height_in_bytes = height * kPointerSize; | 1111 unsigned height_in_bytes = height * kPointerSize; |
| 1112 if (trace_scope_ != NULL) { | 1112 if (trace_scope_ != NULL) { |
| 1113 PrintF(trace_scope_->file(), | 1113 PrintF(trace_scope_->file(), |
| 1114 " translating arguments adaptor => height=%d\n", height_in_bytes); | 1114 " translating arguments adaptor => height=%d\n", height_in_bytes); |
| 1115 } | 1115 } |
| 1116 | 1116 |
| 1117 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize; | 1117 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize; |
| 1118 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 1118 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
| 1119 | 1119 |
| 1120 // Allocate and store the output frame description. | 1120 // Allocate and store the output frame description. |
| 1121 FrameDescription* output_frame = | 1121 FrameDescription* output_frame = |
| 1122 new(output_frame_size) FrameDescription(output_frame_size, function); | 1122 new(output_frame_size) FrameDescription(output_frame_size, function); |
| 1123 output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR); | 1123 output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR); |
| 1124 | 1124 |
| 1125 // Arguments adaptor can not be topmost or bottommost. | 1125 // Arguments adaptor can not be topmost or bottommost. |
| 1126 ASSERT(frame_index > 0 && frame_index < output_count_ - 1); | 1126 CHECK(frame_index > 0 && frame_index < output_count_ - 1); |
| 1127 ASSERT(output_[frame_index] == NULL); | 1127 CHECK(output_[frame_index] == NULL); |
| 1128 output_[frame_index] = output_frame; | 1128 output_[frame_index] = output_frame; |
| 1129 | 1129 |
| 1130 // The top address of the frame is computed from the previous | 1130 // The top address of the frame is computed from the previous |
| 1131 // frame's top and this frame's size. | 1131 // frame's top and this frame's size. |
| 1132 intptr_t top_address; | 1132 intptr_t top_address; |
| 1133 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; | 1133 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
| 1134 output_frame->SetTop(top_address); | 1134 output_frame->SetTop(top_address); |
| 1135 | 1135 |
| 1136 // Compute the incoming parameter translation. | 1136 // Compute the incoming parameter translation. |
| 1137 int parameter_count = height; | 1137 int parameter_count = height; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1263 int parameter_count = height; | 1263 int parameter_count = height; |
| 1264 unsigned output_offset = output_frame_size; | 1264 unsigned output_offset = output_frame_size; |
| 1265 for (int i = 0; i < parameter_count; ++i) { | 1265 for (int i = 0; i < parameter_count; ++i) { |
| 1266 output_offset -= kPointerSize; | 1266 output_offset -= kPointerSize; |
| 1267 int deferred_object_index = deferred_objects_.length(); | 1267 int deferred_object_index = deferred_objects_.length(); |
| 1268 DoTranslateCommand(iterator, frame_index, output_offset); | 1268 DoTranslateCommand(iterator, frame_index, output_offset); |
| 1269 // The allocated receiver of a construct stub frame is passed as the | 1269 // The allocated receiver of a construct stub frame is passed as the |
| 1270 // receiver parameter through the translation. It might be encoding | 1270 // receiver parameter through the translation. It might be encoding |
| 1271 // a captured object, patch the slot address for a captured object. | 1271 // a captured object, patch the slot address for a captured object. |
| 1272 if (i == 0 && deferred_objects_.length() > deferred_object_index) { | 1272 if (i == 0 && deferred_objects_.length() > deferred_object_index) { |
| 1273 ASSERT(!deferred_objects_[deferred_object_index].is_arguments()); | 1273 CHECK(!deferred_objects_[deferred_object_index].is_arguments()); |
| 1274 deferred_objects_[deferred_object_index].patch_slot_address(top_address); | 1274 deferred_objects_[deferred_object_index].patch_slot_address(top_address); |
| 1275 } | 1275 } |
| 1276 } | 1276 } |
| 1277 | 1277 |
| 1278 // Read caller's PC from the previous frame. | 1278 // Read caller's PC from the previous frame. |
| 1279 output_offset -= kPCOnStackSize; | 1279 output_offset -= kPCOnStackSize; |
| 1280 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); | 1280 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); |
| 1281 output_frame->SetCallerPc(output_offset, callers_pc); | 1281 output_frame->SetCallerPc(output_offset, callers_pc); |
| 1282 if (trace_scope_ != NULL) { | 1282 if (trace_scope_ != NULL) { |
| 1283 PrintF(trace_scope_->file(), | 1283 PrintF(trace_scope_->file(), |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1374 output_offset -= kPointerSize; | 1374 output_offset -= kPointerSize; |
| 1375 value = output_frame->GetFrameSlot(output_frame_size - kPointerSize); | 1375 value = output_frame->GetFrameSlot(output_frame_size - kPointerSize); |
| 1376 output_frame->SetFrameSlot(output_offset, value); | 1376 output_frame->SetFrameSlot(output_offset, value); |
| 1377 if (trace_scope_ != NULL) { | 1377 if (trace_scope_ != NULL) { |
| 1378 PrintF(trace_scope_->file(), | 1378 PrintF(trace_scope_->file(), |
| 1379 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1379 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 1380 V8PRIxPTR " ; allocated receiver\n", | 1380 V8PRIxPTR " ; allocated receiver\n", |
| 1381 top_address + output_offset, output_offset, value); | 1381 top_address + output_offset, output_offset, value); |
| 1382 } | 1382 } |
| 1383 | 1383 |
| 1384 ASSERT(0 == output_offset); | 1384 CHECK_EQ(0, output_offset); |
| 1385 | 1385 |
| 1386 intptr_t pc = reinterpret_cast<intptr_t>( | 1386 intptr_t pc = reinterpret_cast<intptr_t>( |
| 1387 construct_stub->instruction_start() + | 1387 construct_stub->instruction_start() + |
| 1388 isolate_->heap()->construct_stub_deopt_pc_offset()->value()); | 1388 isolate_->heap()->construct_stub_deopt_pc_offset()->value()); |
| 1389 output_frame->SetPc(pc); | 1389 output_frame->SetPc(pc); |
| 1390 if (FLAG_enable_ool_constant_pool) { | 1390 if (FLAG_enable_ool_constant_pool) { |
| 1391 intptr_t constant_pool_value = | 1391 intptr_t constant_pool_value = |
| 1392 reinterpret_cast<intptr_t>(construct_stub->constant_pool()); | 1392 reinterpret_cast<intptr_t>(construct_stub->constant_pool()); |
| 1393 output_frame->SetConstantPool(constant_pool_value); | 1393 output_frame->SetConstantPool(constant_pool_value); |
| 1394 } | 1394 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1420 (is_setter_stub_frame ? 1 : 0); | 1420 (is_setter_stub_frame ? 1 : 0); |
| 1421 unsigned fixed_frame_size = fixed_frame_entries * kPointerSize; | 1421 unsigned fixed_frame_size = fixed_frame_entries * kPointerSize; |
| 1422 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 1422 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
| 1423 | 1423 |
| 1424 // Allocate and store the output frame description. | 1424 // Allocate and store the output frame description. |
| 1425 FrameDescription* output_frame = | 1425 FrameDescription* output_frame = |
| 1426 new(output_frame_size) FrameDescription(output_frame_size, accessor); | 1426 new(output_frame_size) FrameDescription(output_frame_size, accessor); |
| 1427 output_frame->SetFrameType(StackFrame::INTERNAL); | 1427 output_frame->SetFrameType(StackFrame::INTERNAL); |
| 1428 | 1428 |
| 1429 // A frame for an accessor stub can not be the topmost or bottommost one. | 1429 // A frame for an accessor stub can not be the topmost or bottommost one. |
| 1430 ASSERT(frame_index > 0 && frame_index < output_count_ - 1); | 1430 CHECK(frame_index > 0 && frame_index < output_count_ - 1); |
| 1431 ASSERT(output_[frame_index] == NULL); | 1431 CHECK_EQ(output_[frame_index], NULL); |
| 1432 output_[frame_index] = output_frame; | 1432 output_[frame_index] = output_frame; |
| 1433 | 1433 |
| 1434 // The top address of the frame is computed from the previous frame's top and | 1434 // The top address of the frame is computed from the previous frame's top and |
| 1435 // this frame's size. | 1435 // this frame's size. |
| 1436 intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size; | 1436 intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
| 1437 output_frame->SetTop(top_address); | 1437 output_frame->SetTop(top_address); |
| 1438 | 1438 |
| 1439 unsigned output_offset = output_frame_size; | 1439 unsigned output_offset = output_frame_size; |
| 1440 | 1440 |
| 1441 // Read caller's PC from the previous frame. | 1441 // Read caller's PC from the previous frame. |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1505 value = reinterpret_cast<intptr_t>(accessor_stub); | 1505 value = reinterpret_cast<intptr_t>(accessor_stub); |
| 1506 output_frame->SetFrameSlot(output_offset, value); | 1506 output_frame->SetFrameSlot(output_offset, value); |
| 1507 if (trace_scope_ != NULL) { | 1507 if (trace_scope_ != NULL) { |
| 1508 PrintF(trace_scope_->file(), | 1508 PrintF(trace_scope_->file(), |
| 1509 " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR | 1509 " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR |
| 1510 " ; code object\n", | 1510 " ; code object\n", |
| 1511 top_address + output_offset, output_offset, value); | 1511 top_address + output_offset, output_offset, value); |
| 1512 } | 1512 } |
| 1513 | 1513 |
| 1514 // Skip receiver. | 1514 // Skip receiver. |
| 1515 Translation::Opcode opcode = | 1515 DoTranslateObjectAndSkip(iterator); |
| 1516 static_cast<Translation::Opcode>(iterator->Next()); | |
| 1517 iterator->Skip(Translation::NumberOfOperandsFor(opcode)); | |
| 1518 | 1516 |
| 1519 if (is_setter_stub_frame) { | 1517 if (is_setter_stub_frame) { |
| 1520 // The implicit return value was part of the artificial setter stub | 1518 // The implicit return value was part of the artificial setter stub |
| 1521 // environment. | 1519 // environment. |
| 1522 output_offset -= kPointerSize; | 1520 output_offset -= kPointerSize; |
| 1523 DoTranslateCommand(iterator, frame_index, output_offset); | 1521 DoTranslateCommand(iterator, frame_index, output_offset); |
| 1524 } | 1522 } |
| 1525 | 1523 |
| 1526 ASSERT(0 == output_offset); | 1524 CHECK_EQ(output_offset, 0); |
| 1527 | 1525 |
| 1528 Smi* offset = is_setter_stub_frame ? | 1526 Smi* offset = is_setter_stub_frame ? |
| 1529 isolate_->heap()->setter_stub_deopt_pc_offset() : | 1527 isolate_->heap()->setter_stub_deopt_pc_offset() : |
| 1530 isolate_->heap()->getter_stub_deopt_pc_offset(); | 1528 isolate_->heap()->getter_stub_deopt_pc_offset(); |
| 1531 intptr_t pc = reinterpret_cast<intptr_t>( | 1529 intptr_t pc = reinterpret_cast<intptr_t>( |
| 1532 accessor_stub->instruction_start() + offset->value()); | 1530 accessor_stub->instruction_start() + offset->value()); |
| 1533 output_frame->SetPc(pc); | 1531 output_frame->SetPc(pc); |
| 1534 if (FLAG_enable_ool_constant_pool) { | 1532 if (FLAG_enable_ool_constant_pool) { |
| 1535 intptr_t constant_pool_value = | 1533 intptr_t constant_pool_value = |
| 1536 reinterpret_cast<intptr_t>(accessor_stub->constant_pool()); | 1534 reinterpret_cast<intptr_t>(accessor_stub->constant_pool()); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1566 // and spilled to stack | .... | | 1564 // and spilled to stack | .... | |
| 1567 // +-------------------------+ | 1565 // +-------------------------+ |
| 1568 // | caller stack param n | | 1566 // | caller stack param n | |
| 1569 // +-------------------------+<-spreg | 1567 // +-------------------------+<-spreg |
| 1570 // reg = number of parameters | 1568 // reg = number of parameters |
| 1571 // reg = failure handler address | 1569 // reg = failure handler address |
| 1572 // reg = saved frame | 1570 // reg = saved frame |
| 1573 // reg = JSFunction context | 1571 // reg = JSFunction context |
| 1574 // | 1572 // |
| 1575 | 1573 |
| 1576 ASSERT(compiled_code_->is_crankshafted() && | 1574 CHECK(compiled_code_->is_crankshafted() && |
| 1577 compiled_code_->kind() != Code::OPTIMIZED_FUNCTION); | 1575 compiled_code_->kind() != Code::OPTIMIZED_FUNCTION); |
| 1578 int major_key = compiled_code_->major_key(); | 1576 int major_key = compiled_code_->major_key(); |
| 1579 CodeStubInterfaceDescriptor* descriptor = | 1577 CodeStubInterfaceDescriptor* descriptor = |
| 1580 isolate_->code_stub_interface_descriptor(major_key); | 1578 isolate_->code_stub_interface_descriptor(major_key); |
| 1581 | 1579 |
| 1582 // The output frame must have room for all pushed register parameters | 1580 // The output frame must have room for all pushed register parameters |
| 1583 // and the standard stack frame slots. Include space for an argument | 1581 // and the standard stack frame slots. Include space for an argument |
| 1584 // object to the callee and optionally the space to pass the argument | 1582 // object to the callee and optionally the space to pass the argument |
| 1585 // object to the stub failure handler. | 1583 // object to the stub failure handler. |
| 1586 ASSERT(descriptor->register_param_count_ >= 0); | 1584 CHECK_GE(descriptor->register_param_count_, 0); |
| 1587 int height_in_bytes = kPointerSize * descriptor->register_param_count_ + | 1585 int height_in_bytes = kPointerSize * descriptor->register_param_count_ + |
| 1588 sizeof(Arguments) + kPointerSize; | 1586 sizeof(Arguments) + kPointerSize; |
| 1589 int fixed_frame_size = StandardFrameConstants::kFixedFrameSize; | 1587 int fixed_frame_size = StandardFrameConstants::kFixedFrameSize; |
| 1590 int input_frame_size = input_->GetFrameSize(); | 1588 int input_frame_size = input_->GetFrameSize(); |
| 1591 int output_frame_size = height_in_bytes + fixed_frame_size; | 1589 int output_frame_size = height_in_bytes + fixed_frame_size; |
| 1592 if (trace_scope_ != NULL) { | 1590 if (trace_scope_ != NULL) { |
| 1593 PrintF(trace_scope_->file(), | 1591 PrintF(trace_scope_->file(), |
| 1594 " translating %s => StubFailureTrampolineStub, height=%d\n", | 1592 " translating %s => StubFailureTrampolineStub, height=%d\n", |
| 1595 CodeStub::MajorName(static_cast<CodeStub::Major>(major_key), false), | 1593 CodeStub::MajorName(static_cast<CodeStub::Major>(major_key), false), |
| 1596 height_in_bytes); | 1594 height_in_bytes); |
| 1597 } | 1595 } |
| 1598 | 1596 |
| 1599 // The stub failure trampoline is a single frame. | 1597 // The stub failure trampoline is a single frame. |
| 1600 FrameDescription* output_frame = | 1598 FrameDescription* output_frame = |
| 1601 new(output_frame_size) FrameDescription(output_frame_size, NULL); | 1599 new(output_frame_size) FrameDescription(output_frame_size, NULL); |
| 1602 output_frame->SetFrameType(StackFrame::STUB_FAILURE_TRAMPOLINE); | 1600 output_frame->SetFrameType(StackFrame::STUB_FAILURE_TRAMPOLINE); |
| 1603 ASSERT(frame_index == 0); | 1601 CHECK_EQ(frame_index, 0); |
| 1604 output_[frame_index] = output_frame; | 1602 output_[frame_index] = output_frame; |
| 1605 | 1603 |
| 1606 // The top address for the output frame can be computed from the input | 1604 // The top address for the output frame can be computed from the input |
| 1607 // frame pointer and the output frame's height. Subtract space for the | 1605 // frame pointer and the output frame's height. Subtract space for the |
| 1608 // context and function slots. | 1606 // context and function slots. |
| 1609 Register fp_reg = StubFailureTrampolineFrame::fp_register(); | 1607 Register fp_reg = StubFailureTrampolineFrame::fp_register(); |
| 1610 intptr_t top_address = input_->GetRegister(fp_reg.code()) - | 1608 intptr_t top_address = input_->GetRegister(fp_reg.code()) - |
| 1611 StandardFrameConstants::kFixedFrameSizeFromFp - height_in_bytes; | 1609 StandardFrameConstants::kFixedFrameSizeFromFp - height_in_bytes; |
| 1612 output_frame->SetTop(top_address); | 1610 output_frame->SetTop(top_address); |
| 1613 | 1611 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1651 } | 1649 } |
| 1652 } | 1650 } |
| 1653 | 1651 |
| 1654 // The context can be gotten from the input frame. | 1652 // The context can be gotten from the input frame. |
| 1655 Register context_reg = StubFailureTrampolineFrame::context_register(); | 1653 Register context_reg = StubFailureTrampolineFrame::context_register(); |
| 1656 input_frame_offset -= kPointerSize; | 1654 input_frame_offset -= kPointerSize; |
| 1657 value = input_->GetFrameSlot(input_frame_offset); | 1655 value = input_->GetFrameSlot(input_frame_offset); |
| 1658 output_frame->SetRegister(context_reg.code(), value); | 1656 output_frame->SetRegister(context_reg.code(), value); |
| 1659 output_frame_offset -= kPointerSize; | 1657 output_frame_offset -= kPointerSize; |
| 1660 output_frame->SetFrameSlot(output_frame_offset, value); | 1658 output_frame->SetFrameSlot(output_frame_offset, value); |
| 1661 ASSERT(reinterpret_cast<Object*>(value)->IsContext()); | 1659 CHECK(reinterpret_cast<Object*>(value)->IsContext()); |
| 1662 if (trace_scope_ != NULL) { | 1660 if (trace_scope_ != NULL) { |
| 1663 PrintF(trace_scope_->file(), | 1661 PrintF(trace_scope_->file(), |
| 1664 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1662 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 1665 V8PRIxPTR " ; context\n", | 1663 V8PRIxPTR " ; context\n", |
| 1666 top_address + output_frame_offset, output_frame_offset, value); | 1664 top_address + output_frame_offset, output_frame_offset, value); |
| 1667 } | 1665 } |
| 1668 | 1666 |
| 1669 // A marker value is used in place of the function. | 1667 // A marker value is used in place of the function. |
| 1670 output_frame_offset -= kPointerSize; | 1668 output_frame_offset -= kPointerSize; |
| 1671 value = reinterpret_cast<intptr_t>( | 1669 value = reinterpret_cast<intptr_t>( |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1729 int arguments_length_offset = -1; | 1727 int arguments_length_offset = -1; |
| 1730 for (int i = 0; i < descriptor->register_param_count_; ++i) { | 1728 for (int i = 0; i < descriptor->register_param_count_; ++i) { |
| 1731 output_frame_offset -= kPointerSize; | 1729 output_frame_offset -= kPointerSize; |
| 1732 DoTranslateCommand(iterator, 0, output_frame_offset); | 1730 DoTranslateCommand(iterator, 0, output_frame_offset); |
| 1733 | 1731 |
| 1734 if (!arg_count_known && descriptor->IsParameterCountRegister(i)) { | 1732 if (!arg_count_known && descriptor->IsParameterCountRegister(i)) { |
| 1735 arguments_length_offset = output_frame_offset; | 1733 arguments_length_offset = output_frame_offset; |
| 1736 } | 1734 } |
| 1737 } | 1735 } |
| 1738 | 1736 |
| 1739 ASSERT(0 == output_frame_offset); | 1737 CHECK_EQ(output_frame_offset, 0); |
| 1740 | 1738 |
| 1741 if (!arg_count_known) { | 1739 if (!arg_count_known) { |
| 1742 ASSERT(arguments_length_offset >= 0); | 1740 CHECK_GE(arguments_length_offset, 0); |
| 1743 // We know it's a smi because 1) the code stub guarantees the stack | 1741 // We know it's a smi because 1) the code stub guarantees the stack |
| 1744 // parameter count is in smi range, and 2) the DoTranslateCommand in the | 1742 // parameter count is in smi range, and 2) the DoTranslateCommand in the |
| 1745 // parameter loop above translated that to a tagged value. | 1743 // parameter loop above translated that to a tagged value. |
| 1746 Smi* smi_caller_arg_count = reinterpret_cast<Smi*>( | 1744 Smi* smi_caller_arg_count = reinterpret_cast<Smi*>( |
| 1747 output_frame->GetFrameSlot(arguments_length_offset)); | 1745 output_frame->GetFrameSlot(arguments_length_offset)); |
| 1748 caller_arg_count = smi_caller_arg_count->value(); | 1746 caller_arg_count = smi_caller_arg_count->value(); |
| 1749 output_frame->SetFrameSlot(length_frame_offset, caller_arg_count); | 1747 output_frame->SetFrameSlot(length_frame_offset, caller_arg_count); |
| 1750 if (trace_scope_ != NULL) { | 1748 if (trace_scope_ != NULL) { |
| 1751 PrintF(trace_scope_->file(), | 1749 PrintF(trace_scope_->file(), |
| 1752 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1750 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1816 for (int i = 0; i < length; ++i) { | 1814 for (int i = 0; i < length; ++i) { |
| 1817 MaterializeNextValue(); | 1815 MaterializeNextValue(); |
| 1818 } | 1816 } |
| 1819 } else if (desc.is_arguments()) { | 1817 } else if (desc.is_arguments()) { |
| 1820 // Construct an arguments object and copy the parameters to a newly | 1818 // Construct an arguments object and copy the parameters to a newly |
| 1821 // allocated arguments object backing store. | 1819 // allocated arguments object backing store. |
| 1822 Handle<JSFunction> function = ArgumentsObjectFunction(object_index); | 1820 Handle<JSFunction> function = ArgumentsObjectFunction(object_index); |
| 1823 Handle<JSObject> arguments = | 1821 Handle<JSObject> arguments = |
| 1824 isolate_->factory()->NewArgumentsObject(function, length); | 1822 isolate_->factory()->NewArgumentsObject(function, length); |
| 1825 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length); | 1823 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length); |
| 1826 ASSERT(array->length() == length); | 1824 ASSERT_EQ(array->length(), length); |
| 1827 arguments->set_elements(*array); | 1825 arguments->set_elements(*array); |
| 1828 materialized_objects_->Add(arguments); | 1826 materialized_objects_->Add(arguments); |
| 1829 for (int i = 0; i < length; ++i) { | 1827 for (int i = 0; i < length; ++i) { |
| 1830 Handle<Object> value = MaterializeNextValue(); | 1828 Handle<Object> value = MaterializeNextValue(); |
| 1831 array->set(i, *value); | 1829 array->set(i, *value); |
| 1832 } | 1830 } |
| 1833 } else { | 1831 } else { |
| 1834 // Dispatch on the instance type of the object to be materialized. | 1832 // Dispatch on the instance type of the object to be materialized. |
| 1835 // We also need to make sure that the representation of all fields | 1833 // We also need to make sure that the representation of all fields |
| 1836 // in the given object are general enough to hold a tagged value. | 1834 // in the given object are general enough to hold a tagged value. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1882 Handle<Object> elements = MaterializeNextValue(); | 1880 Handle<Object> elements = MaterializeNextValue(); |
| 1883 Handle<Object> length = MaterializeNextValue(); | 1881 Handle<Object> length = MaterializeNextValue(); |
| 1884 object->set_properties(FixedArray::cast(*properties)); | 1882 object->set_properties(FixedArray::cast(*properties)); |
| 1885 object->set_elements(FixedArrayBase::cast(*elements)); | 1883 object->set_elements(FixedArrayBase::cast(*elements)); |
| 1886 object->set_length(*length); | 1884 object->set_length(*length); |
| 1887 break; | 1885 break; |
| 1888 } | 1886 } |
| 1889 default: | 1887 default: |
| 1890 PrintF(stderr, | 1888 PrintF(stderr, |
| 1891 "[couldn't handle instance type %d]\n", map->instance_type()); | 1889 "[couldn't handle instance type %d]\n", map->instance_type()); |
| 1892 UNREACHABLE(); | 1890 FATAL("Unsupported instance type"); |
| 1893 } | 1891 } |
| 1894 } | 1892 } |
| 1895 | 1893 |
| 1896 return materialized_objects_->at(object_index); | 1894 return materialized_objects_->at(object_index); |
| 1897 } | 1895 } |
| 1898 | 1896 |
| 1899 | 1897 |
| 1900 Handle<Object> Deoptimizer::MaterializeNextValue() { | 1898 Handle<Object> Deoptimizer::MaterializeNextValue() { |
| 1901 int value_index = materialization_value_index_++; | 1899 int value_index = materialization_value_index_++; |
| 1902 Handle<Object> value = materialized_values_->at(value_index); | 1900 Handle<Object> value = materialized_values_->at(value_index); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1976 | 1974 |
| 1977 while (materialization_object_index_ < deferred_objects_.length()) { | 1975 while (materialization_object_index_ < deferred_objects_.length()) { |
| 1978 int object_index = materialization_object_index_; | 1976 int object_index = materialization_object_index_; |
| 1979 ObjectMaterializationDescriptor descriptor = | 1977 ObjectMaterializationDescriptor descriptor = |
| 1980 deferred_objects_.at(object_index); | 1978 deferred_objects_.at(object_index); |
| 1981 | 1979 |
| 1982 // Find a previously materialized object by de-duplication or | 1980 // Find a previously materialized object by de-duplication or |
| 1983 // materialize a new instance of the object if necessary. Store | 1981 // materialize a new instance of the object if necessary. Store |
| 1984 // the materialized object into the frame slot. | 1982 // the materialized object into the frame slot. |
| 1985 Handle<Object> object = MaterializeNextHeapObject(); | 1983 Handle<Object> object = MaterializeNextHeapObject(); |
| 1986 Memory::Object_at(descriptor.slot_address()) = *object; | 1984 if (descriptor.slot_address() != NULL) { |
| 1985 Memory::Object_at(descriptor.slot_address()) = *object; |
| 1986 } |
| 1987 if (trace_scope_ != NULL) { | 1987 if (trace_scope_ != NULL) { |
| 1988 if (descriptor.is_arguments()) { | 1988 if (descriptor.is_arguments()) { |
| 1989 PrintF(trace_scope_->file(), | 1989 PrintF(trace_scope_->file(), |
| 1990 "Materialized %sarguments object of length %d for %p: ", | 1990 "Materialized %sarguments object of length %d for %p: ", |
| 1991 ArgumentsObjectIsAdapted(object_index) ? "(adapted) " : "", | 1991 ArgumentsObjectIsAdapted(object_index) ? "(adapted) " : "", |
| 1992 Handle<JSObject>::cast(object)->elements()->length(), | 1992 Handle<JSObject>::cast(object)->elements()->length(), |
| 1993 reinterpret_cast<void*>(descriptor.slot_address())); | 1993 reinterpret_cast<void*>(descriptor.slot_address())); |
| 1994 } else { | 1994 } else { |
| 1995 PrintF(trace_scope_->file(), | 1995 PrintF(trace_scope_->file(), |
| 1996 "Materialized captured object of size %d for %p: ", | 1996 "Materialized captured object of size %d for %p: ", |
| 1997 Handle<HeapObject>::cast(object)->Size(), | 1997 Handle<HeapObject>::cast(object)->Size(), |
| 1998 reinterpret_cast<void*>(descriptor.slot_address())); | 1998 reinterpret_cast<void*>(descriptor.slot_address())); |
| 1999 } | 1999 } |
| 2000 object->ShortPrint(trace_scope_->file()); | 2000 object->ShortPrint(trace_scope_->file()); |
| 2001 PrintF(trace_scope_->file(), "\n"); | 2001 PrintF(trace_scope_->file(), "\n"); |
| 2002 } | 2002 } |
| 2003 } | 2003 } |
| 2004 | 2004 |
| 2005 ASSERT(materialization_object_index_ == materialized_objects_->length()); | 2005 CHECK_EQ(materialization_object_index_, materialized_objects_->length()); |
| 2006 ASSERT(materialization_value_index_ == materialized_values_->length()); | 2006 CHECK_EQ(materialization_value_index_, materialized_values_->length()); |
| 2007 } | 2007 } |
| 2008 | 2008 |
| 2009 if (prev_materialized_count_ > 0) { | 2009 if (prev_materialized_count_ > 0) { |
| 2010 materialized_store->Remove(stack_fp_); | 2010 materialized_store->Remove(stack_fp_); |
| 2011 } | 2011 } |
| 2012 } | 2012 } |
| 2013 | 2013 |
| 2014 | 2014 |
| 2015 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( | 2015 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( |
| 2016 Address parameters_top, | 2016 Address parameters_top, |
| 2017 uint32_t parameters_size, | 2017 uint32_t parameters_size, |
| 2018 Address expressions_top, | 2018 Address expressions_top, |
| 2019 uint32_t expressions_size, | 2019 uint32_t expressions_size, |
| 2020 DeoptimizedFrameInfo* info) { | 2020 DeoptimizedFrameInfo* info) { |
| 2021 ASSERT_EQ(DEBUGGER, bailout_type_); | 2021 CHECK_EQ(DEBUGGER, bailout_type_); |
| 2022 Address parameters_bottom = parameters_top + parameters_size; | 2022 Address parameters_bottom = parameters_top + parameters_size; |
| 2023 Address expressions_bottom = expressions_top + expressions_size; | 2023 Address expressions_bottom = expressions_top + expressions_size; |
| 2024 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { | 2024 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { |
| 2025 HeapNumberMaterializationDescriptor<Address> d = deferred_heap_numbers_[i]; | 2025 HeapNumberMaterializationDescriptor<Address> d = deferred_heap_numbers_[i]; |
| 2026 | 2026 |
| 2027 // Check of the heap number to materialize actually belong to the frame | 2027 // Check of the heap number to materialize actually belong to the frame |
| 2028 // being extracted. | 2028 // being extracted. |
| 2029 Address slot = d.destination(); | 2029 Address slot = d.destination(); |
| 2030 if (parameters_top <= slot && slot < parameters_bottom) { | 2030 if (parameters_top <= slot && slot < parameters_bottom) { |
| 2031 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); | 2031 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2068 | 2068 |
| 2069 static const char* TraceValueType(bool is_smi) { | 2069 static const char* TraceValueType(bool is_smi) { |
| 2070 if (is_smi) { | 2070 if (is_smi) { |
| 2071 return "smi"; | 2071 return "smi"; |
| 2072 } | 2072 } |
| 2073 | 2073 |
| 2074 return "heap number"; | 2074 return "heap number"; |
| 2075 } | 2075 } |
| 2076 | 2076 |
| 2077 | 2077 |
| 2078 void Deoptimizer::DoTranslateObjectAndSkip(TranslationIterator* iterator) { |
| 2079 Translation::Opcode opcode = |
| 2080 static_cast<Translation::Opcode>(iterator->Next()); |
| 2081 |
| 2082 switch (opcode) { |
| 2083 case Translation::BEGIN: |
| 2084 case Translation::JS_FRAME: |
| 2085 case Translation::ARGUMENTS_ADAPTOR_FRAME: |
| 2086 case Translation::CONSTRUCT_STUB_FRAME: |
| 2087 case Translation::GETTER_STUB_FRAME: |
| 2088 case Translation::SETTER_STUB_FRAME: |
| 2089 case Translation::COMPILED_STUB_FRAME: { |
| 2090 FATAL("Unexpected frame start translation opcode"); |
| 2091 return; |
| 2092 } |
| 2093 |
| 2094 case Translation::REGISTER: |
| 2095 case Translation::INT32_REGISTER: |
| 2096 case Translation::UINT32_REGISTER: |
| 2097 case Translation::DOUBLE_REGISTER: |
| 2098 case Translation::STACK_SLOT: |
| 2099 case Translation::INT32_STACK_SLOT: |
| 2100 case Translation::UINT32_STACK_SLOT: |
| 2101 case Translation::DOUBLE_STACK_SLOT: |
| 2102 case Translation::LITERAL: { |
| 2103 // The value is not part of any materialized object, so we can ignore it. |
| 2104 iterator->Skip(Translation::NumberOfOperandsFor(opcode)); |
| 2105 return; |
| 2106 } |
| 2107 |
| 2108 case Translation::DUPLICATED_OBJECT: { |
| 2109 int object_index = iterator->Next(); |
| 2110 if (trace_scope_ != NULL) { |
| 2111 PrintF(trace_scope_->file(), " skipping object "); |
| 2112 PrintF(trace_scope_->file(), |
| 2113 " ; duplicate of object #%d\n", object_index); |
| 2114 } |
| 2115 AddObjectDuplication(0, object_index); |
| 2116 return; |
| 2117 } |
| 2118 |
| 2119 case Translation::ARGUMENTS_OBJECT: |
| 2120 case Translation::CAPTURED_OBJECT: { |
| 2121 int length = iterator->Next(); |
| 2122 bool is_args = opcode == Translation::ARGUMENTS_OBJECT; |
| 2123 if (trace_scope_ != NULL) { |
| 2124 PrintF(trace_scope_->file(), " skipping object "); |
| 2125 PrintF(trace_scope_->file(), |
| 2126 " ; object (length = %d, is_args = %d)\n", length, is_args); |
| 2127 } |
| 2128 |
| 2129 AddObjectStart(0, length, is_args); |
| 2130 |
| 2131 // We save the object values on the side and materialize the actual |
| 2132 // object after the deoptimized frame is built. |
| 2133 int object_index = deferred_objects_.length() - 1; |
| 2134 for (int i = 0; i < length; i++) { |
| 2135 DoTranslateObject(iterator, object_index, i); |
| 2136 } |
| 2137 return; |
| 2138 } |
| 2139 } |
| 2140 |
| 2141 FATAL("Unexpected translation opcode"); |
| 2142 } |
| 2143 |
| 2144 |
| 2078 void Deoptimizer::DoTranslateObject(TranslationIterator* iterator, | 2145 void Deoptimizer::DoTranslateObject(TranslationIterator* iterator, |
| 2079 int object_index, | 2146 int object_index, |
| 2080 int field_index) { | 2147 int field_index) { |
| 2081 disasm::NameConverter converter; | 2148 disasm::NameConverter converter; |
| 2082 Address object_slot = deferred_objects_[object_index].slot_address(); | 2149 Address object_slot = deferred_objects_[object_index].slot_address(); |
| 2083 | 2150 |
| 2084 Translation::Opcode opcode = | 2151 Translation::Opcode opcode = |
| 2085 static_cast<Translation::Opcode>(iterator->Next()); | 2152 static_cast<Translation::Opcode>(iterator->Next()); |
| 2086 | 2153 |
| 2087 switch (opcode) { | 2154 switch (opcode) { |
| 2088 case Translation::BEGIN: | 2155 case Translation::BEGIN: |
| 2089 case Translation::JS_FRAME: | 2156 case Translation::JS_FRAME: |
| 2090 case Translation::ARGUMENTS_ADAPTOR_FRAME: | 2157 case Translation::ARGUMENTS_ADAPTOR_FRAME: |
| 2091 case Translation::CONSTRUCT_STUB_FRAME: | 2158 case Translation::CONSTRUCT_STUB_FRAME: |
| 2092 case Translation::GETTER_STUB_FRAME: | 2159 case Translation::GETTER_STUB_FRAME: |
| 2093 case Translation::SETTER_STUB_FRAME: | 2160 case Translation::SETTER_STUB_FRAME: |
| 2094 case Translation::COMPILED_STUB_FRAME: | 2161 case Translation::COMPILED_STUB_FRAME: |
| 2095 UNREACHABLE(); | 2162 FATAL("Unexpected frame start translation opcode"); |
| 2096 return; | 2163 return; |
| 2097 | 2164 |
| 2098 case Translation::REGISTER: { | 2165 case Translation::REGISTER: { |
| 2099 int input_reg = iterator->Next(); | 2166 int input_reg = iterator->Next(); |
| 2100 intptr_t input_value = input_->GetRegister(input_reg); | 2167 intptr_t input_value = input_->GetRegister(input_reg); |
| 2101 if (trace_scope_ != NULL) { | 2168 if (trace_scope_ != NULL) { |
| 2102 PrintF(trace_scope_->file(), | 2169 PrintF(trace_scope_->file(), |
| 2103 " object @0x%08" V8PRIxPTR ": [field #%d] <- ", | 2170 " object @0x%08" V8PRIxPTR ": [field #%d] <- ", |
| 2104 reinterpret_cast<intptr_t>(object_slot), | 2171 reinterpret_cast<intptr_t>(object_slot), |
| 2105 field_index); | 2172 field_index); |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2325 AddObjectTaggedValue(value); | 2392 AddObjectTaggedValue(value); |
| 2326 // We save the object values on the side and materialize the actual | 2393 // We save the object values on the side and materialize the actual |
| 2327 // object after the deoptimized frame is built. | 2394 // object after the deoptimized frame is built. |
| 2328 int object_index = deferred_objects_.length() - 1; | 2395 int object_index = deferred_objects_.length() - 1; |
| 2329 for (int i = 0; i < length; i++) { | 2396 for (int i = 0; i < length; i++) { |
| 2330 DoTranslateObject(iterator, object_index, i); | 2397 DoTranslateObject(iterator, object_index, i); |
| 2331 } | 2398 } |
| 2332 return; | 2399 return; |
| 2333 } | 2400 } |
| 2334 } | 2401 } |
| 2402 |
| 2403 FATAL("Unexpected translation opcode"); |
| 2335 } | 2404 } |
| 2336 | 2405 |
| 2337 | 2406 |
| 2338 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, | 2407 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, |
| 2339 int frame_index, | 2408 int frame_index, |
| 2340 unsigned output_offset) { | 2409 unsigned output_offset) { |
| 2341 disasm::NameConverter converter; | 2410 disasm::NameConverter converter; |
| 2342 // A GC-safe temporary placeholder that we can put in the output frame. | 2411 // A GC-safe temporary placeholder that we can put in the output frame. |
| 2343 const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0)); | 2412 const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0)); |
| 2344 | 2413 |
| 2345 Translation::Opcode opcode = | 2414 Translation::Opcode opcode = |
| 2346 static_cast<Translation::Opcode>(iterator->Next()); | 2415 static_cast<Translation::Opcode>(iterator->Next()); |
| 2347 | 2416 |
| 2348 switch (opcode) { | 2417 switch (opcode) { |
| 2349 case Translation::BEGIN: | 2418 case Translation::BEGIN: |
| 2350 case Translation::JS_FRAME: | 2419 case Translation::JS_FRAME: |
| 2351 case Translation::ARGUMENTS_ADAPTOR_FRAME: | 2420 case Translation::ARGUMENTS_ADAPTOR_FRAME: |
| 2352 case Translation::CONSTRUCT_STUB_FRAME: | 2421 case Translation::CONSTRUCT_STUB_FRAME: |
| 2353 case Translation::GETTER_STUB_FRAME: | 2422 case Translation::GETTER_STUB_FRAME: |
| 2354 case Translation::SETTER_STUB_FRAME: | 2423 case Translation::SETTER_STUB_FRAME: |
| 2355 case Translation::COMPILED_STUB_FRAME: | 2424 case Translation::COMPILED_STUB_FRAME: |
| 2356 UNREACHABLE(); | 2425 FATAL("Unexpected translation opcode"); |
| 2357 return; | 2426 return; |
| 2358 | 2427 |
| 2359 case Translation::REGISTER: { | 2428 case Translation::REGISTER: { |
| 2360 int input_reg = iterator->Next(); | 2429 int input_reg = iterator->Next(); |
| 2361 intptr_t input_value = input_->GetRegister(input_reg); | 2430 intptr_t input_value = input_->GetRegister(input_reg); |
| 2362 if (trace_scope_ != NULL) { | 2431 if (trace_scope_ != NULL) { |
| 2363 PrintF( | 2432 PrintF( |
| 2364 trace_scope_->file(), | 2433 trace_scope_->file(), |
| 2365 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s ", | 2434 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s ", |
| 2366 output_[frame_index]->GetTop() + output_offset, | 2435 output_[frame_index]->GetTop() + output_offset, |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2639 // pointer, function, context, and all the incoming arguments. | 2708 // pointer, function, context, and all the incoming arguments. |
| 2640 return ComputeIncomingArgumentSize(function) + | 2709 return ComputeIncomingArgumentSize(function) + |
| 2641 StandardFrameConstants::kFixedFrameSize; | 2710 StandardFrameConstants::kFixedFrameSize; |
| 2642 } | 2711 } |
| 2643 | 2712 |
| 2644 | 2713 |
| 2645 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { | 2714 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { |
| 2646 // The incoming arguments is the values for formal parameters and | 2715 // The incoming arguments is the values for formal parameters and |
| 2647 // the receiver. Every slot contains a pointer. | 2716 // the receiver. Every slot contains a pointer. |
| 2648 if (function->IsSmi()) { | 2717 if (function->IsSmi()) { |
| 2649 ASSERT(Smi::cast(function) == Smi::FromInt(StackFrame::STUB)); | 2718 CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB)); |
| 2650 return 0; | 2719 return 0; |
| 2651 } | 2720 } |
| 2652 unsigned arguments = function->shared()->formal_parameter_count() + 1; | 2721 unsigned arguments = function->shared()->formal_parameter_count() + 1; |
| 2653 return arguments * kPointerSize; | 2722 return arguments * kPointerSize; |
| 2654 } | 2723 } |
| 2655 | 2724 |
| 2656 | 2725 |
| 2657 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const { | 2726 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const { |
| 2658 DeoptimizationInputData* data = DeoptimizationInputData::cast( | 2727 DeoptimizationInputData* data = DeoptimizationInputData::cast( |
| 2659 compiled_code_->deoptimization_data()); | 2728 compiled_code_->deoptimization_data()); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2704 } | 2773 } |
| 2705 | 2774 |
| 2706 | 2775 |
| 2707 void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate, | 2776 void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate, |
| 2708 BailoutType type, | 2777 BailoutType type, |
| 2709 int max_entry_id) { | 2778 int max_entry_id) { |
| 2710 // We cannot run this if the serializer is enabled because this will | 2779 // We cannot run this if the serializer is enabled because this will |
| 2711 // cause us to emit relocation information for the external | 2780 // cause us to emit relocation information for the external |
| 2712 // references. This is fine because the deoptimizer's code section | 2781 // references. This is fine because the deoptimizer's code section |
| 2713 // isn't meant to be serialized at all. | 2782 // isn't meant to be serialized at all. |
| 2714 ASSERT(type == EAGER || type == SOFT || type == LAZY); | 2783 CHECK(type == EAGER || type == SOFT || type == LAZY); |
| 2715 DeoptimizerData* data = isolate->deoptimizer_data(); | 2784 DeoptimizerData* data = isolate->deoptimizer_data(); |
| 2716 int entry_count = data->deopt_entry_code_entries_[type]; | 2785 int entry_count = data->deopt_entry_code_entries_[type]; |
| 2717 if (max_entry_id < entry_count) return; | 2786 if (max_entry_id < entry_count) return; |
| 2718 entry_count = Max(entry_count, Deoptimizer::kMinNumberOfEntries); | 2787 entry_count = Max(entry_count, Deoptimizer::kMinNumberOfEntries); |
| 2719 while (max_entry_id >= entry_count) entry_count *= 2; | 2788 while (max_entry_id >= entry_count) entry_count *= 2; |
| 2720 ASSERT(entry_count <= Deoptimizer::kMaxNumberOfEntries); | 2789 CHECK(entry_count <= Deoptimizer::kMaxNumberOfEntries); |
| 2721 | 2790 |
| 2722 MacroAssembler masm(isolate, NULL, 16 * KB); | 2791 MacroAssembler masm(isolate, NULL, 16 * KB); |
| 2723 masm.set_emit_debug_code(false); | 2792 masm.set_emit_debug_code(false); |
| 2724 GenerateDeoptimizationEntries(&masm, entry_count, type); | 2793 GenerateDeoptimizationEntries(&masm, entry_count, type); |
| 2725 CodeDesc desc; | 2794 CodeDesc desc; |
| 2726 masm.GetCode(&desc); | 2795 masm.GetCode(&desc); |
| 2727 ASSERT(!RelocInfo::RequiresRelocation(desc)); | 2796 ASSERT(!RelocInfo::RequiresRelocation(desc)); |
| 2728 | 2797 |
| 2729 MemoryChunk* chunk = data->deopt_entry_code_[type]; | 2798 MemoryChunk* chunk = data->deopt_entry_code_[type]; |
| 2730 ASSERT(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >= | 2799 CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >= |
| 2731 desc.instr_size); | 2800 desc.instr_size); |
| 2732 chunk->CommitArea(desc.instr_size); | 2801 chunk->CommitArea(desc.instr_size); |
| 2733 CopyBytes(chunk->area_start(), desc.buffer, | 2802 CopyBytes(chunk->area_start(), desc.buffer, |
| 2734 static_cast<size_t>(desc.instr_size)); | 2803 static_cast<size_t>(desc.instr_size)); |
| 2735 CPU::FlushICache(chunk->area_start(), desc.instr_size); | 2804 CPU::FlushICache(chunk->area_start(), desc.instr_size); |
| 2736 | 2805 |
| 2737 data->deopt_entry_code_entries_[type] = entry_count; | 2806 data->deopt_entry_code_entries_[type] = entry_count; |
| 2738 } | 2807 } |
| 2739 | 2808 |
| 2740 | 2809 |
| 2741 FrameDescription::FrameDescription(uint32_t frame_size, | 2810 FrameDescription::FrameDescription(uint32_t frame_size, |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2788 case StackFrame::JAVA_SCRIPT: | 2857 case StackFrame::JAVA_SCRIPT: |
| 2789 return function_->shared()->formal_parameter_count(); | 2858 return function_->shared()->formal_parameter_count(); |
| 2790 case StackFrame::ARGUMENTS_ADAPTOR: { | 2859 case StackFrame::ARGUMENTS_ADAPTOR: { |
| 2791 // Last slot contains number of incomming arguments as a smi. | 2860 // Last slot contains number of incomming arguments as a smi. |
| 2792 // Can't use GetExpression(0) because it would cause infinite recursion. | 2861 // Can't use GetExpression(0) because it would cause infinite recursion. |
| 2793 return reinterpret_cast<Smi*>(*GetFrameSlotPointer(0))->value(); | 2862 return reinterpret_cast<Smi*>(*GetFrameSlotPointer(0))->value(); |
| 2794 } | 2863 } |
| 2795 case StackFrame::STUB: | 2864 case StackFrame::STUB: |
| 2796 return -1; // Minus receiver. | 2865 return -1; // Minus receiver. |
| 2797 default: | 2866 default: |
| 2798 UNREACHABLE(); | 2867 FATAL("Unexpected stack frame type"); |
| 2799 return 0; | 2868 return 0; |
| 2800 } | 2869 } |
| 2801 } | 2870 } |
| 2802 | 2871 |
| 2803 | 2872 |
| 2804 Object* FrameDescription::GetParameter(int index) { | 2873 Object* FrameDescription::GetParameter(int index) { |
| 2805 ASSERT(index >= 0); | 2874 CHECK_GE(index, 0); |
| 2806 ASSERT(index < ComputeParametersCount()); | 2875 CHECK_LT(index, ComputeParametersCount()); |
| 2807 // The slot indexes for incoming arguments are negative. | 2876 // The slot indexes for incoming arguments are negative. |
| 2808 unsigned offset = GetOffsetFromSlotIndex(index - ComputeParametersCount()); | 2877 unsigned offset = GetOffsetFromSlotIndex(index - ComputeParametersCount()); |
| 2809 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); | 2878 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); |
| 2810 } | 2879 } |
| 2811 | 2880 |
| 2812 | 2881 |
| 2813 unsigned FrameDescription::GetExpressionCount() { | 2882 unsigned FrameDescription::GetExpressionCount() { |
| 2814 ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_); | 2883 CHECK_EQ(StackFrame::JAVA_SCRIPT, type_); |
| 2815 unsigned size = GetFrameSize() - ComputeFixedSize(); | 2884 unsigned size = GetFrameSize() - ComputeFixedSize(); |
| 2816 return size / kPointerSize; | 2885 return size / kPointerSize; |
| 2817 } | 2886 } |
| 2818 | 2887 |
| 2819 | 2888 |
| 2820 Object* FrameDescription::GetExpression(int index) { | 2889 Object* FrameDescription::GetExpression(int index) { |
| 2821 ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_); | 2890 ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_); |
| 2822 unsigned offset = GetOffsetFromSlotIndex(index); | 2891 unsigned offset = GetOffsetFromSlotIndex(index); |
| 2823 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); | 2892 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); |
| 2824 } | 2893 } |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3006 case LITERAL: | 3075 case LITERAL: |
| 3007 case COMPILED_STUB_FRAME: | 3076 case COMPILED_STUB_FRAME: |
| 3008 return 1; | 3077 return 1; |
| 3009 case BEGIN: | 3078 case BEGIN: |
| 3010 case ARGUMENTS_ADAPTOR_FRAME: | 3079 case ARGUMENTS_ADAPTOR_FRAME: |
| 3011 case CONSTRUCT_STUB_FRAME: | 3080 case CONSTRUCT_STUB_FRAME: |
| 3012 return 2; | 3081 return 2; |
| 3013 case JS_FRAME: | 3082 case JS_FRAME: |
| 3014 return 3; | 3083 return 3; |
| 3015 } | 3084 } |
| 3016 UNREACHABLE(); | 3085 FATAL("Unexpected translation type"); |
| 3017 return -1; | 3086 return -1; |
| 3018 } | 3087 } |
| 3019 | 3088 |
| 3020 | 3089 |
| 3021 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) | 3090 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) |
| 3022 | 3091 |
| 3023 const char* Translation::StringFor(Opcode opcode) { | 3092 const char* Translation::StringFor(Opcode opcode) { |
| 3024 #define TRANSLATION_OPCODE_CASE(item) case item: return #item; | 3093 #define TRANSLATION_OPCODE_CASE(item) case item: return #item; |
| 3025 switch (opcode) { | 3094 switch (opcode) { |
| 3026 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE) | 3095 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE) |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3116 int formal_parameter_count) | 3185 int formal_parameter_count) |
| 3117 : current_slot_(0), args_length_(-1), first_slot_index_(-1) { | 3186 : current_slot_(0), args_length_(-1), first_slot_index_(-1) { |
| 3118 DisallowHeapAllocation no_gc; | 3187 DisallowHeapAllocation no_gc; |
| 3119 | 3188 |
| 3120 int deopt_index = Safepoint::kNoDeoptimizationIndex; | 3189 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
| 3121 DeoptimizationInputData* data = | 3190 DeoptimizationInputData* data = |
| 3122 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); | 3191 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); |
| 3123 TranslationIterator it(data->TranslationByteArray(), | 3192 TranslationIterator it(data->TranslationByteArray(), |
| 3124 data->TranslationIndex(deopt_index)->value()); | 3193 data->TranslationIndex(deopt_index)->value()); |
| 3125 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | 3194 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
| 3126 ASSERT(opcode == Translation::BEGIN); | 3195 CHECK_EQ(opcode, Translation::BEGIN); |
| 3127 it.Next(); // Drop frame count. | 3196 it.Next(); // Drop frame count. |
| 3128 | 3197 |
| 3129 stack_frame_id_ = frame->fp(); | 3198 stack_frame_id_ = frame->fp(); |
| 3130 | 3199 |
| 3131 int jsframe_count = it.Next(); | 3200 int jsframe_count = it.Next(); |
| 3132 USE(jsframe_count); | 3201 CHECK_GT(jsframe_count, inlined_jsframe_index); |
| 3133 ASSERT(jsframe_count > inlined_jsframe_index); | |
| 3134 int jsframes_to_skip = inlined_jsframe_index; | 3202 int jsframes_to_skip = inlined_jsframe_index; |
| 3135 int number_of_slots = -1; // Number of slots inside our frame (yet unknown) | 3203 int number_of_slots = -1; // Number of slots inside our frame (yet unknown) |
| 3136 bool should_deopt = false; | 3204 bool should_deopt = false; |
| 3137 while (number_of_slots != 0) { | 3205 while (number_of_slots != 0) { |
| 3138 opcode = static_cast<Translation::Opcode>(it.Next()); | 3206 opcode = static_cast<Translation::Opcode>(it.Next()); |
| 3139 bool processed = false; | 3207 bool processed = false; |
| 3140 if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) { | 3208 if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) { |
| 3141 if (jsframes_to_skip == 0) { | 3209 if (jsframes_to_skip == 0) { |
| 3142 ASSERT(Translation::NumberOfOperandsFor(opcode) == 2); | 3210 CHECK_EQ(Translation::NumberOfOperandsFor(opcode), 2); |
| 3143 | 3211 |
| 3144 it.Skip(1); // literal id | 3212 it.Skip(1); // literal id |
| 3145 int height = it.Next(); | 3213 int height = it.Next(); |
| 3146 | 3214 |
| 3147 // Skip the translation command for the receiver. | 3215 // Skip the translation command for the receiver. |
| 3148 it.Skip(Translation::NumberOfOperandsFor( | 3216 it.Skip(Translation::NumberOfOperandsFor( |
| 3149 static_cast<Translation::Opcode>(it.Next()))); | 3217 static_cast<Translation::Opcode>(it.Next()))); |
| 3150 | 3218 |
| 3151 // We reached the arguments adaptor frame corresponding to the | 3219 // We reached the arguments adaptor frame corresponding to the |
| 3152 // inlined function in question. Number of arguments is height - 1. | 3220 // inlined function in question. Number of arguments is height - 1. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3179 opcode != Translation::GETTER_STUB_FRAME && | 3247 opcode != Translation::GETTER_STUB_FRAME && |
| 3180 opcode != Translation::SETTER_STUB_FRAME && | 3248 opcode != Translation::SETTER_STUB_FRAME && |
| 3181 opcode != Translation::COMPILED_STUB_FRAME) { | 3249 opcode != Translation::COMPILED_STUB_FRAME) { |
| 3182 slot_refs_.Add(ComputeSlotForNextArgument(opcode, &it, data, frame)); | 3250 slot_refs_.Add(ComputeSlotForNextArgument(opcode, &it, data, frame)); |
| 3183 | 3251 |
| 3184 if (first_slot_index_ >= 0) { | 3252 if (first_slot_index_ >= 0) { |
| 3185 // We have found the beginning of our frame -> make sure we count | 3253 // We have found the beginning of our frame -> make sure we count |
| 3186 // the nested slots of captured objects | 3254 // the nested slots of captured objects |
| 3187 number_of_slots--; | 3255 number_of_slots--; |
| 3188 SlotRef& slot = slot_refs_.last(); | 3256 SlotRef& slot = slot_refs_.last(); |
| 3189 ASSERT(slot.Representation() != SlotRef::ARGUMENTS_OBJECT); | 3257 CHECK_NE(slot.Representation(), SlotRef::ARGUMENTS_OBJECT); |
| 3190 number_of_slots += slot.GetChildrenCount(); | 3258 number_of_slots += slot.GetChildrenCount(); |
| 3191 if (slot.Representation() == SlotRef::DEFERRED_OBJECT || | 3259 if (slot.Representation() == SlotRef::DEFERRED_OBJECT || |
| 3192 slot.Representation() == SlotRef::DUPLICATE_OBJECT) { | 3260 slot.Representation() == SlotRef::DUPLICATE_OBJECT) { |
| 3193 should_deopt = true; | 3261 should_deopt = true; |
| 3194 } | 3262 } |
| 3195 } | 3263 } |
| 3196 | 3264 |
| 3197 processed = true; | 3265 processed = true; |
| 3198 } | 3266 } |
| 3199 if (!processed) { | 3267 if (!processed) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3253 previously_materialized_objects_ = materialized_store->Get(stack_frame_id_); | 3321 previously_materialized_objects_ = materialized_store->Get(stack_frame_id_); |
| 3254 prev_materialized_count_ = previously_materialized_objects_.is_null() | 3322 prev_materialized_count_ = previously_materialized_objects_.is_null() |
| 3255 ? 0 : previously_materialized_objects_->length(); | 3323 ? 0 : previously_materialized_objects_->length(); |
| 3256 | 3324 |
| 3257 // Skip any materialized objects of the inlined "parent" frames. | 3325 // Skip any materialized objects of the inlined "parent" frames. |
| 3258 // (Note that we still need to materialize them because they might be | 3326 // (Note that we still need to materialize them because they might be |
| 3259 // referred to as duplicated objects.) | 3327 // referred to as duplicated objects.) |
| 3260 while (current_slot_ < first_slot_index_) { | 3328 while (current_slot_ < first_slot_index_) { |
| 3261 GetNext(isolate, 0); | 3329 GetNext(isolate, 0); |
| 3262 } | 3330 } |
| 3263 ASSERT(current_slot_ == first_slot_index_); | 3331 CHECK_EQ(current_slot_, first_slot_index_); |
| 3264 } | 3332 } |
| 3265 | 3333 |
| 3266 | 3334 |
| 3267 Handle<Object> SlotRefValueBuilder::GetPreviouslyMaterialized( | 3335 Handle<Object> SlotRefValueBuilder::GetPreviouslyMaterialized( |
| 3268 Isolate* isolate, int length) { | 3336 Isolate* isolate, int length) { |
| 3269 int object_index = materialized_objects_.length(); | 3337 int object_index = materialized_objects_.length(); |
| 3270 Handle<Object> return_value = Handle<Object>( | 3338 Handle<Object> return_value = Handle<Object>( |
| 3271 previously_materialized_objects_->get(object_index), isolate); | 3339 previously_materialized_objects_->get(object_index), isolate); |
| 3272 materialized_objects_.Add(return_value); | 3340 materialized_objects_.Add(return_value); |
| 3273 | 3341 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3315 materialized_objects_.Add(isolate->factory()->undefined_value()); | 3383 materialized_objects_.Add(isolate->factory()->undefined_value()); |
| 3316 int length = slot.GetChildrenCount(); | 3384 int length = slot.GetChildrenCount(); |
| 3317 for (int i = 0; i < length; ++i) { | 3385 for (int i = 0; i < length; ++i) { |
| 3318 // We don't need the argument, just ignore it | 3386 // We don't need the argument, just ignore it |
| 3319 GetNext(isolate, lvl + 1); | 3387 GetNext(isolate, lvl + 1); |
| 3320 } | 3388 } |
| 3321 return isolate->factory()->undefined_value(); | 3389 return isolate->factory()->undefined_value(); |
| 3322 } | 3390 } |
| 3323 case SlotRef::DEFERRED_OBJECT: { | 3391 case SlotRef::DEFERRED_OBJECT: { |
| 3324 int length = slot.GetChildrenCount(); | 3392 int length = slot.GetChildrenCount(); |
| 3325 ASSERT(slot_refs_[current_slot_].Representation() == SlotRef::LITERAL || | 3393 CHECK(slot_refs_[current_slot_].Representation() == SlotRef::LITERAL || |
| 3326 slot_refs_[current_slot_].Representation() == SlotRef::TAGGED); | 3394 slot_refs_[current_slot_].Representation() == SlotRef::TAGGED); |
| 3327 | 3395 |
| 3328 int object_index = materialized_objects_.length(); | 3396 int object_index = materialized_objects_.length(); |
| 3329 if (object_index < prev_materialized_count_) { | 3397 if (object_index < prev_materialized_count_) { |
| 3330 return GetPreviouslyMaterialized(isolate, length); | 3398 return GetPreviouslyMaterialized(isolate, length); |
| 3331 } | 3399 } |
| 3332 | 3400 |
| 3333 Handle<Object> map_object = slot_refs_[current_slot_].GetValue(isolate); | 3401 Handle<Object> map_object = slot_refs_[current_slot_].GetValue(isolate); |
| 3334 Handle<Map> map = Map::GeneralizeAllFieldRepresentations( | 3402 Handle<Map> map = Map::GeneralizeAllFieldRepresentations( |
| 3335 Handle<Map>::cast(map_object)); | 3403 Handle<Map>::cast(map_object)); |
| 3336 current_slot_++; | 3404 current_slot_++; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3377 object->set_length(*length); | 3445 object->set_length(*length); |
| 3378 return object; | 3446 return object; |
| 3379 } | 3447 } |
| 3380 default: | 3448 default: |
| 3381 PrintF(stderr, | 3449 PrintF(stderr, |
| 3382 "[couldn't handle instance type %d]\n", map->instance_type()); | 3450 "[couldn't handle instance type %d]\n", map->instance_type()); |
| 3383 UNREACHABLE(); | 3451 UNREACHABLE(); |
| 3384 break; | 3452 break; |
| 3385 } | 3453 } |
| 3386 UNREACHABLE(); | 3454 UNREACHABLE(); |
| 3455 break; |
| 3387 } | 3456 } |
| 3388 | 3457 |
| 3389 case SlotRef::DUPLICATE_OBJECT: { | 3458 case SlotRef::DUPLICATE_OBJECT: { |
| 3390 int object_index = slot.DuplicateObjectId(); | 3459 int object_index = slot.DuplicateObjectId(); |
| 3391 Handle<Object> object = materialized_objects_[object_index]; | 3460 Handle<Object> object = materialized_objects_[object_index]; |
| 3392 materialized_objects_.Add(object); | 3461 materialized_objects_.Add(object); |
| 3393 return object; | 3462 return object; |
| 3394 } | 3463 } |
| 3395 default: | 3464 default: |
| 3396 UNREACHABLE(); | 3465 UNREACHABLE(); |
| 3397 break; | 3466 break; |
| 3398 } | 3467 } |
| 3399 | 3468 |
| 3400 FATAL("We should never get here - unexpected deopt slot kind."); | 3469 FATAL("We should never get here - unexpected deopt slot kind."); |
| 3401 return Handle<Object>::null(); | 3470 return Handle<Object>::null(); |
| 3402 } | 3471 } |
| 3403 | 3472 |
| 3404 | 3473 |
| 3405 void SlotRefValueBuilder::Finish(Isolate* isolate) { | 3474 void SlotRefValueBuilder::Finish(Isolate* isolate) { |
| 3406 // We should have processed all the slots | 3475 // We should have processed all the slots |
| 3407 ASSERT(slot_refs_.length() == current_slot_); | 3476 CHECK_EQ(slot_refs_.length(), current_slot_); |
| 3408 | 3477 |
| 3409 if (materialized_objects_.length() > prev_materialized_count_) { | 3478 if (materialized_objects_.length() > prev_materialized_count_) { |
| 3410 // We have materialized some new objects, so we have to store them | 3479 // We have materialized some new objects, so we have to store them |
| 3411 // to prevent duplicate materialization | 3480 // to prevent duplicate materialization |
| 3412 Handle<FixedArray> array = isolate->factory()->NewFixedArray( | 3481 Handle<FixedArray> array = isolate->factory()->NewFixedArray( |
| 3413 materialized_objects_.length()); | 3482 materialized_objects_.length()); |
| 3414 for (int i = 0; i < materialized_objects_.length(); i++) { | 3483 for (int i = 0; i < materialized_objects_.length(); i++) { |
| 3415 array->set(i, *(materialized_objects_.at(i))); | 3484 array->set(i, *(materialized_objects_.at(i))); |
| 3416 } | 3485 } |
| 3417 isolate->materialized_object_store()->Set(stack_frame_id_, array); | 3486 isolate->materialized_object_store()->Set(stack_frame_id_, array); |
| 3418 } | 3487 } |
| 3419 } | 3488 } |
| 3420 | 3489 |
| 3421 | 3490 |
| 3422 Handle<FixedArray> MaterializedObjectStore::Get(Address fp) { | 3491 Handle<FixedArray> MaterializedObjectStore::Get(Address fp) { |
| 3423 int index = StackIdToIndex(fp); | 3492 int index = StackIdToIndex(fp); |
| 3424 if (index == -1) { | 3493 if (index == -1) { |
| 3425 return Handle<FixedArray>::null(); | 3494 return Handle<FixedArray>::null(); |
| 3426 } | 3495 } |
| 3427 Handle<FixedArray> array = GetStackEntries(); | 3496 Handle<FixedArray> array = GetStackEntries(); |
| 3428 ASSERT(array->length() > index); | 3497 CHECK_GT(array->length(), index); |
| 3429 return Handle<FixedArray>::cast(Handle<Object>(array->get(index), | 3498 return Handle<FixedArray>::cast(Handle<Object>(array->get(index), |
| 3430 isolate())); | 3499 isolate())); |
| 3431 } | 3500 } |
| 3432 | 3501 |
| 3433 | 3502 |
| 3434 void MaterializedObjectStore::Set(Address fp, | 3503 void MaterializedObjectStore::Set(Address fp, |
| 3435 Handle<FixedArray> materialized_objects) { | 3504 Handle<FixedArray> materialized_objects) { |
| 3436 int index = StackIdToIndex(fp); | 3505 int index = StackIdToIndex(fp); |
| 3437 if (index == -1) { | 3506 if (index == -1) { |
| 3438 index = frame_fps_.length(); | 3507 index = frame_fps_.length(); |
| 3439 frame_fps_.Add(fp); | 3508 frame_fps_.Add(fp); |
| 3440 } | 3509 } |
| 3441 | 3510 |
| 3442 Handle<FixedArray> array = EnsureStackEntries(index + 1); | 3511 Handle<FixedArray> array = EnsureStackEntries(index + 1); |
| 3443 array->set(index, *materialized_objects); | 3512 array->set(index, *materialized_objects); |
| 3444 } | 3513 } |
| 3445 | 3514 |
| 3446 | 3515 |
| 3447 void MaterializedObjectStore::Remove(Address fp) { | 3516 void MaterializedObjectStore::Remove(Address fp) { |
| 3448 int index = StackIdToIndex(fp); | 3517 int index = StackIdToIndex(fp); |
| 3449 ASSERT(index >= 0); | 3518 CHECK_GE(index, 0); |
| 3450 | 3519 |
| 3451 frame_fps_.Remove(index); | 3520 frame_fps_.Remove(index); |
| 3452 Handle<FixedArray> array = GetStackEntries(); | 3521 Handle<FixedArray> array = GetStackEntries(); |
| 3453 ASSERT(array->length() > index); | 3522 CHECK_LT(index, array->length()); |
| 3454 for (int i = index; i < frame_fps_.length(); i++) { | 3523 for (int i = index; i < frame_fps_.length(); i++) { |
| 3455 array->set(i, array->get(i + 1)); | 3524 array->set(i, array->get(i + 1)); |
| 3456 } | 3525 } |
| 3457 array->set(frame_fps_.length(), isolate()->heap()->undefined_value()); | 3526 array->set(frame_fps_.length(), isolate()->heap()->undefined_value()); |
| 3458 } | 3527 } |
| 3459 | 3528 |
| 3460 | 3529 |
| 3461 int MaterializedObjectStore::StackIdToIndex(Address fp) { | 3530 int MaterializedObjectStore::StackIdToIndex(Address fp) { |
| 3462 for (int i = 0; i < frame_fps_.length(); i++) { | 3531 for (int i = 0; i < frame_fps_.length(); i++) { |
| 3463 if (frame_fps_[i] == fp) { | 3532 if (frame_fps_[i] == fp) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3510 Address pc = reinterpret_cast<Address>(output_frame->GetPc()); | 3579 Address pc = reinterpret_cast<Address>(output_frame->GetPc()); |
| 3511 Code* code = Code::cast(deoptimizer->isolate()->FindCodeObject(pc)); | 3580 Code* code = Code::cast(deoptimizer->isolate()->FindCodeObject(pc)); |
| 3512 source_position_ = code->SourcePosition(pc); | 3581 source_position_ = code->SourcePosition(pc); |
| 3513 | 3582 |
| 3514 for (int i = 0; i < expression_count_; i++) { | 3583 for (int i = 0; i < expression_count_; i++) { |
| 3515 SetExpression(i, output_frame->GetExpression(i)); | 3584 SetExpression(i, output_frame->GetExpression(i)); |
| 3516 } | 3585 } |
| 3517 | 3586 |
| 3518 if (has_arguments_adaptor) { | 3587 if (has_arguments_adaptor) { |
| 3519 output_frame = deoptimizer->output_[frame_index - 1]; | 3588 output_frame = deoptimizer->output_[frame_index - 1]; |
| 3520 ASSERT(output_frame->GetFrameType() == StackFrame::ARGUMENTS_ADAPTOR); | 3589 CHECK_EQ(output_frame->GetFrameType(), StackFrame::ARGUMENTS_ADAPTOR); |
| 3521 } | 3590 } |
| 3522 | 3591 |
| 3523 parameters_count_ = output_frame->ComputeParametersCount(); | 3592 parameters_count_ = output_frame->ComputeParametersCount(); |
| 3524 parameters_ = new Object*[parameters_count_]; | 3593 parameters_ = new Object*[parameters_count_]; |
| 3525 for (int i = 0; i < parameters_count_; i++) { | 3594 for (int i = 0; i < parameters_count_; i++) { |
| 3526 SetParameter(i, output_frame->GetParameter(i)); | 3595 SetParameter(i, output_frame->GetParameter(i)); |
| 3527 } | 3596 } |
| 3528 } | 3597 } |
| 3529 | 3598 |
| 3530 | 3599 |
| 3531 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { | 3600 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { |
| 3532 delete[] expression_stack_; | 3601 delete[] expression_stack_; |
| 3533 delete[] parameters_; | 3602 delete[] parameters_; |
| 3534 } | 3603 } |
| 3535 | 3604 |
| 3536 | 3605 |
| 3537 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | 3606 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
| 3538 v->VisitPointer(BitCast<Object**>(&function_)); | 3607 v->VisitPointer(BitCast<Object**>(&function_)); |
| 3539 v->VisitPointers(parameters_, parameters_ + parameters_count_); | 3608 v->VisitPointers(parameters_, parameters_ + parameters_count_); |
| 3540 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | 3609 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
| 3541 } | 3610 } |
| 3542 | 3611 |
| 3543 } } // namespace v8::internal | 3612 } } // namespace v8::internal |
| OLD | NEW |