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