| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 | 72 |
| 73 #ifdef ENABLE_DEBUGGER_SUPPORT | 73 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 74 void DeoptimizerData::Iterate(ObjectVisitor* v) { | 74 void DeoptimizerData::Iterate(ObjectVisitor* v) { |
| 75 if (deoptimized_frame_info_ != NULL) { | 75 if (deoptimized_frame_info_ != NULL) { |
| 76 deoptimized_frame_info_->Iterate(v); | 76 deoptimized_frame_info_->Iterate(v); |
| 77 } | 77 } |
| 78 } | 78 } |
| 79 #endif | 79 #endif |
| 80 | 80 |
| 81 | 81 |
| 82 Code* DeoptimizerData::FindDeoptimizingCode(Address addr) { |
| 83 for (DeoptimizingCodeListNode* node = deoptimizing_code_list_; |
| 84 node != NULL; |
| 85 node = node->next()) { |
| 86 if (node->code()->contains(addr)) return *node->code(); |
| 87 } |
| 88 return NULL; |
| 89 } |
| 90 |
| 91 |
| 92 void DeoptimizerData::RemoveDeoptimizingCode(Code* code) { |
| 93 for (DeoptimizingCodeListNode *prev = NULL, *cur = deoptimizing_code_list_; |
| 94 cur != NULL; |
| 95 prev = cur, cur = cur->next()) { |
| 96 if (*cur->code() == code) { |
| 97 if (prev == NULL) { |
| 98 deoptimizing_code_list_ = cur->next(); |
| 99 } else { |
| 100 prev->set_next(cur->next()); |
| 101 } |
| 102 delete cur; |
| 103 return; |
| 104 } |
| 105 } |
| 106 // Deoptimizing code is removed through weak callback. Each object is expected |
| 107 // to be removed once and only once. |
| 108 UNREACHABLE(); |
| 109 } |
| 110 |
| 111 |
| 82 // We rely on this function not causing a GC. It is called from generated code | 112 // We rely on this function not causing a GC. It is called from generated code |
| 83 // without having a real stack frame in place. | 113 // without having a real stack frame in place. |
| 84 Deoptimizer* Deoptimizer::New(JSFunction* function, | 114 Deoptimizer* Deoptimizer::New(JSFunction* function, |
| 85 BailoutType type, | 115 BailoutType type, |
| 86 unsigned bailout_id, | 116 unsigned bailout_id, |
| 87 Address from, | 117 Address from, |
| 88 int fp_to_sp_delta, | 118 int fp_to_sp_delta, |
| 89 Isolate* isolate) { | 119 Isolate* isolate) { |
| 90 ASSERT(isolate == Isolate::Current()); | 120 ASSERT(isolate == Isolate::Current()); |
| 91 Deoptimizer* deoptimizer = new Deoptimizer(isolate, | 121 Deoptimizer* deoptimizer = new Deoptimizer(isolate, |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 | 449 |
| 420 // Run through the list of all native contexts and deoptimize. | 450 // Run through the list of all native contexts and deoptimize. |
| 421 Object* context = Isolate::Current()->heap()->native_contexts_list(); | 451 Object* context = Isolate::Current()->heap()->native_contexts_list(); |
| 422 while (!context->IsUndefined()) { | 452 while (!context->IsUndefined()) { |
| 423 DeoptimizeAllFunctionsForContext(Context::cast(context), filter); | 453 DeoptimizeAllFunctionsForContext(Context::cast(context), filter); |
| 424 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); | 454 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); |
| 425 } | 455 } |
| 426 } | 456 } |
| 427 | 457 |
| 428 | 458 |
| 429 void Deoptimizer::HandleWeakDeoptimizedCode( | 459 void Deoptimizer::HandleWeakDeoptimizedCode(v8::Persistent<v8::Value> obj, |
| 430 v8::Persistent<v8::Value> obj, void* data) { | 460 void* parameter) { |
| 431 DeoptimizingCodeListNode* node = | 461 DeoptimizingCodeListNode* node = |
| 432 reinterpret_cast<DeoptimizingCodeListNode*>(data); | 462 reinterpret_cast<DeoptimizingCodeListNode*>(parameter); |
| 433 RemoveDeoptimizingCode(*node->code()); | 463 DeoptimizerData* data = Isolate::Current()->deoptimizer_data(); |
| 464 data->RemoveDeoptimizingCode(*node->code()); |
| 434 #ifdef DEBUG | 465 #ifdef DEBUG |
| 435 node = Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_; | 466 for (DeoptimizingCodeListNode* current = data->deoptimizing_code_list_; |
| 436 while (node != NULL) { | 467 current != NULL; |
| 437 ASSERT(node != reinterpret_cast<DeoptimizingCodeListNode*>(data)); | 468 current = current->next()) { |
| 438 node = node->next(); | 469 ASSERT(current != node); |
| 439 } | 470 } |
| 440 #endif | 471 #endif |
| 441 } | 472 } |
| 442 | 473 |
| 443 | 474 |
| 444 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) { | 475 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) { |
| 445 deoptimizer->DoComputeOutputFrames(); | 476 deoptimizer->DoComputeOutputFrames(); |
| 446 } | 477 } |
| 447 | 478 |
| 448 | 479 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 unsigned id = Deoptimizer::GetDeoptimizationId( | 543 unsigned id = Deoptimizer::GetDeoptimizationId( |
| 513 info->target_address(), Deoptimizer::EAGER); | 544 info->target_address(), Deoptimizer::EAGER); |
| 514 if (id == bailout_id && last_comment != NULL) { | 545 if (id == bailout_id && last_comment != NULL) { |
| 515 PrintF(" %s\n", last_comment); | 546 PrintF(" %s\n", last_comment); |
| 516 break; | 547 break; |
| 517 } | 548 } |
| 518 } | 549 } |
| 519 } | 550 } |
| 520 } | 551 } |
| 521 } else if (type == LAZY) { | 552 } else if (type == LAZY) { |
| 522 compiled_code_ = FindDeoptimizingCodeFromAddress(from); | 553 compiled_code_ = isolate->deoptimizer_data()->FindDeoptimizingCode(from); |
| 523 if (compiled_code_ == NULL) { | 554 if (compiled_code_ == NULL) { |
| 524 compiled_code_ = | 555 compiled_code_ = |
| 525 static_cast<Code*>(isolate->heap()->FindCodeObject(from)); | 556 static_cast<Code*>(isolate->heap()->FindCodeObject(from)); |
| 526 } | 557 } |
| 527 ASSERT(compiled_code_ != NULL); | 558 ASSERT(compiled_code_ != NULL); |
| 528 } else if (type == OSR) { | 559 } else if (type == OSR) { |
| 529 // The function has already been optimized and we're transitioning | 560 // The function has already been optimized and we're transitioning |
| 530 // from the unoptimized shared version to the optimized one in the | 561 // from the unoptimized shared version to the optimized one in the |
| 531 // function. The return address (from) points to unoptimized code. | 562 // function. The return address (from) points to unoptimized code. |
| 532 compiled_code_ = function_->code(); | 563 compiled_code_ = function_->code(); |
| (...skipping 994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1527 CPU::FlushICache(memory->address(), desc.instr_size); | 1558 CPU::FlushICache(memory->address(), desc.instr_size); |
| 1528 | 1559 |
| 1529 if (type == EAGER) { | 1560 if (type == EAGER) { |
| 1530 data->eager_deoptimization_entry_code_entries_ = entry_count; | 1561 data->eager_deoptimization_entry_code_entries_ = entry_count; |
| 1531 } else { | 1562 } else { |
| 1532 data->lazy_deoptimization_entry_code_entries_ = entry_count; | 1563 data->lazy_deoptimization_entry_code_entries_ = entry_count; |
| 1533 } | 1564 } |
| 1534 } | 1565 } |
| 1535 | 1566 |
| 1536 | 1567 |
| 1537 Code* Deoptimizer::FindDeoptimizingCodeFromAddress(Address addr) { | |
| 1538 DeoptimizingCodeListNode* node = | |
| 1539 Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_; | |
| 1540 while (node != NULL) { | |
| 1541 if (node->code()->contains(addr)) return *node->code(); | |
| 1542 node = node->next(); | |
| 1543 } | |
| 1544 return NULL; | |
| 1545 } | |
| 1546 | |
| 1547 | |
| 1548 void Deoptimizer::RemoveDeoptimizingCode(Code* code) { | |
| 1549 DeoptimizerData* data = Isolate::Current()->deoptimizer_data(); | |
| 1550 ASSERT(data->deoptimizing_code_list_ != NULL); | |
| 1551 // Run through the code objects to find this one and remove it. | |
| 1552 DeoptimizingCodeListNode* prev = NULL; | |
| 1553 DeoptimizingCodeListNode* current = data->deoptimizing_code_list_; | |
| 1554 while (current != NULL) { | |
| 1555 if (*current->code() == code) { | |
| 1556 // Unlink from list. If prev is NULL we are looking at the first element. | |
| 1557 if (prev == NULL) { | |
| 1558 data->deoptimizing_code_list_ = current->next(); | |
| 1559 } else { | |
| 1560 prev->set_next(current->next()); | |
| 1561 } | |
| 1562 delete current; | |
| 1563 return; | |
| 1564 } | |
| 1565 // Move to next in list. | |
| 1566 prev = current; | |
| 1567 current = current->next(); | |
| 1568 } | |
| 1569 // Deoptimizing code is removed through weak callback. Each object is expected | |
| 1570 // to be removed once and only once. | |
| 1571 UNREACHABLE(); | |
| 1572 } | |
| 1573 | |
| 1574 | |
| 1575 void Deoptimizer::ReplaceCodeForRelatedFunctions(JSFunction* function, | 1568 void Deoptimizer::ReplaceCodeForRelatedFunctions(JSFunction* function, |
| 1576 Code* code) { | 1569 Code* code) { |
| 1577 SharedFunctionInfo* shared = function->shared(); | 1570 SharedFunctionInfo* shared = function->shared(); |
| 1578 Object* undefined = Isolate::Current()->heap()->undefined_value(); | 1571 Object* undefined = Isolate::Current()->heap()->undefined_value(); |
| 1579 Object* current = function; | 1572 Object* current = function; |
| 1580 | 1573 |
| 1581 while (current != undefined) { | 1574 while (current != undefined) { |
| 1582 JSFunction* func = JSFunction::cast(current); | 1575 JSFunction* func = JSFunction::cast(current); |
| 1583 current = func->next_function_link(); | 1576 current = func->next_function_link(); |
| 1584 func->set_code(shared->code()); | 1577 func->set_code(shared->code()); |
| (...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2097 | 2090 |
| 2098 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | 2091 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
| 2099 v->VisitPointer(BitCast<Object**>(&function_)); | 2092 v->VisitPointer(BitCast<Object**>(&function_)); |
| 2100 v->VisitPointers(parameters_, parameters_ + parameters_count_); | 2093 v->VisitPointers(parameters_, parameters_ + parameters_count_); |
| 2101 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | 2094 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
| 2102 } | 2095 } |
| 2103 | 2096 |
| 2104 #endif // ENABLE_DEBUGGER_SUPPORT | 2097 #endif // ENABLE_DEBUGGER_SUPPORT |
| 2105 | 2098 |
| 2106 } } // namespace v8::internal | 2099 } } // namespace v8::internal |
| OLD | NEW |