| 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 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 BailoutType type) { | 278 BailoutType type) { |
| 279 TableEntryGenerator generator(masm, type, count); | 279 TableEntryGenerator generator(masm, type, count); |
| 280 generator.Generate(); | 280 generator.Generate(); |
| 281 } | 281 } |
| 282 | 282 |
| 283 | 283 |
| 284 void Deoptimizer::VisitAllOptimizedFunctionsForContext( | 284 void Deoptimizer::VisitAllOptimizedFunctionsForContext( |
| 285 Context* context, OptimizedFunctionVisitor* visitor) { | 285 Context* context, OptimizedFunctionVisitor* visitor) { |
| 286 Isolate* isolate = context->GetIsolate(); | 286 Isolate* isolate = context->GetIsolate(); |
| 287 ZoneScope zone_scope(isolate->runtime_zone(), DELETE_ON_EXIT); | 287 ZoneScope zone_scope(isolate->runtime_zone(), DELETE_ON_EXIT); |
| 288 AssertNoAllocation no_allocation; | 288 DisallowHeapAllocation no_allocation; |
| 289 | 289 |
| 290 ASSERT(context->IsNativeContext()); | 290 ASSERT(context->IsNativeContext()); |
| 291 | 291 |
| 292 visitor->EnterContext(context); | 292 visitor->EnterContext(context); |
| 293 | 293 |
| 294 // Create a snapshot of the optimized functions list. This is needed because | 294 // Create a snapshot of the optimized functions list. This is needed because |
| 295 // visitors might remove more than one link from the list at once. | 295 // visitors might remove more than one link from the list at once. |
| 296 ZoneList<JSFunction*> snapshot(1, isolate->runtime_zone()); | 296 ZoneList<JSFunction*> snapshot(1, isolate->runtime_zone()); |
| 297 Object* element = context->OptimizedFunctionsListHead(); | 297 Object* element = context->OptimizedFunctionsListHead(); |
| 298 while (!element->IsUndefined()) { | 298 while (!element->IsUndefined()) { |
| 299 JSFunction* element_function = JSFunction::cast(element); | 299 JSFunction* element_function = JSFunction::cast(element); |
| 300 snapshot.Add(element_function, isolate->runtime_zone()); | 300 snapshot.Add(element_function, isolate->runtime_zone()); |
| 301 element = element_function->next_function_link(); | 301 element = element_function->next_function_link(); |
| 302 } | 302 } |
| 303 | 303 |
| 304 // Run through the snapshot of optimized functions and visit them. | 304 // Run through the snapshot of optimized functions and visit them. |
| 305 for (int i = 0; i < snapshot.length(); ++i) { | 305 for (int i = 0; i < snapshot.length(); ++i) { |
| 306 visitor->VisitFunction(snapshot.at(i)); | 306 visitor->VisitFunction(snapshot.at(i)); |
| 307 } | 307 } |
| 308 | 308 |
| 309 visitor->LeaveContext(context); | 309 visitor->LeaveContext(context); |
| 310 } | 310 } |
| 311 | 311 |
| 312 | 312 |
| 313 void Deoptimizer::VisitAllOptimizedFunctions( | 313 void Deoptimizer::VisitAllOptimizedFunctions( |
| 314 Isolate* isolate, | 314 Isolate* isolate, |
| 315 OptimizedFunctionVisitor* visitor) { | 315 OptimizedFunctionVisitor* visitor) { |
| 316 AssertNoAllocation no_allocation; | 316 DisallowHeapAllocation no_allocation; |
| 317 | 317 |
| 318 // Run through the list of all native contexts and deoptimize. | 318 // Run through the list of all native contexts and deoptimize. |
| 319 Object* context = isolate->heap()->native_contexts_list(); | 319 Object* context = isolate->heap()->native_contexts_list(); |
| 320 while (!context->IsUndefined()) { | 320 while (!context->IsUndefined()) { |
| 321 VisitAllOptimizedFunctionsForContext(Context::cast(context), visitor); | 321 VisitAllOptimizedFunctionsForContext(Context::cast(context), visitor); |
| 322 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); | 322 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); |
| 323 } | 323 } |
| 324 } | 324 } |
| 325 | 325 |
| 326 | 326 |
| 327 // Removes the functions selected by the given filter from the optimized | 327 // Removes the functions selected by the given filter from the optimized |
| 328 // function list of the given context and partitions the removed functions | 328 // function list of the given context and partitions the removed functions |
| 329 // into one or more lists such that all functions in a list share the same | 329 // into one or more lists such that all functions in a list share the same |
| 330 // code. The head of each list is written in the deoptimizing_functions field | 330 // code. The head of each list is written in the deoptimizing_functions field |
| 331 // of the corresponding code object. | 331 // of the corresponding code object. |
| 332 // The found code objects are returned in the given zone list. | 332 // The found code objects are returned in the given zone list. |
| 333 static void PartitionOptimizedFunctions(Context* context, | 333 static void PartitionOptimizedFunctions(Context* context, |
| 334 OptimizedFunctionFilter* filter, | 334 OptimizedFunctionFilter* filter, |
| 335 ZoneList<Code*>* partitions, | 335 ZoneList<Code*>* partitions, |
| 336 Zone* zone, | 336 Zone* zone, |
| 337 Object* undefined) { | 337 Object* undefined) { |
| 338 AssertNoAllocation no_allocation; | 338 DisallowHeapAllocation no_allocation; |
| 339 Object* current = context->get(Context::OPTIMIZED_FUNCTIONS_LIST); | 339 Object* current = context->get(Context::OPTIMIZED_FUNCTIONS_LIST); |
| 340 Object* remainder_head = undefined; | 340 Object* remainder_head = undefined; |
| 341 Object* remainder_tail = undefined; | 341 Object* remainder_tail = undefined; |
| 342 ASSERT_EQ(0, partitions->length()); | 342 ASSERT_EQ(0, partitions->length()); |
| 343 while (current != undefined) { | 343 while (current != undefined) { |
| 344 JSFunction* function = JSFunction::cast(current); | 344 JSFunction* function = JSFunction::cast(current); |
| 345 current = function->next_function_link(); | 345 current = function->next_function_link(); |
| 346 if (filter->TakeFunction(function)) { | 346 if (filter->TakeFunction(function)) { |
| 347 Code* code = function->code(); | 347 Code* code = function->code(); |
| 348 if (code->deoptimizing_functions() == undefined) { | 348 if (code->deoptimizing_functions() == undefined) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 explicit DeoptimizeWithMatchingCodeFilter(Code* code) : code_(code) {} | 381 explicit DeoptimizeWithMatchingCodeFilter(Code* code) : code_(code) {} |
| 382 virtual bool TakeFunction(JSFunction* function) { | 382 virtual bool TakeFunction(JSFunction* function) { |
| 383 return function->code() == code_; | 383 return function->code() == code_; |
| 384 } | 384 } |
| 385 private: | 385 private: |
| 386 Code* code_; | 386 Code* code_; |
| 387 }; | 387 }; |
| 388 | 388 |
| 389 | 389 |
| 390 void Deoptimizer::DeoptimizeAll(Isolate* isolate) { | 390 void Deoptimizer::DeoptimizeAll(Isolate* isolate) { |
| 391 AssertNoAllocation no_allocation; | 391 DisallowHeapAllocation no_allocation; |
| 392 | 392 |
| 393 if (FLAG_trace_deopt) { | 393 if (FLAG_trace_deopt) { |
| 394 PrintF("[deoptimize all contexts]\n"); | 394 PrintF("[deoptimize all contexts]\n"); |
| 395 } | 395 } |
| 396 | 396 |
| 397 DeoptimizeAllFilter filter; | 397 DeoptimizeAllFilter filter; |
| 398 DeoptimizeAllFunctionsWith(isolate, &filter); | 398 DeoptimizeAllFunctionsWith(isolate, &filter); |
| 399 } | 399 } |
| 400 | 400 |
| 401 | 401 |
| 402 void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) { | 402 void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) { |
| 403 AssertNoAllocation no_allocation; | 403 DisallowHeapAllocation no_allocation; |
| 404 DeoptimizeAllFilter filter; | 404 DeoptimizeAllFilter filter; |
| 405 if (object->IsJSGlobalProxy()) { | 405 if (object->IsJSGlobalProxy()) { |
| 406 Object* proto = object->GetPrototype(); | 406 Object* proto = object->GetPrototype(); |
| 407 ASSERT(proto->IsJSGlobalObject()); | 407 ASSERT(proto->IsJSGlobalObject()); |
| 408 DeoptimizeAllFunctionsForContext( | 408 DeoptimizeAllFunctionsForContext( |
| 409 GlobalObject::cast(proto)->native_context(), &filter); | 409 GlobalObject::cast(proto)->native_context(), &filter); |
| 410 } else if (object->IsGlobalObject()) { | 410 } else if (object->IsGlobalObject()) { |
| 411 DeoptimizeAllFunctionsForContext( | 411 DeoptimizeAllFunctionsForContext( |
| 412 GlobalObject::cast(object)->native_context(), &filter); | 412 GlobalObject::cast(object)->native_context(), &filter); |
| 413 } | 413 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 444 for (int i = 0; i < codes.length(); ++i) { | 444 for (int i = 0; i < codes.length(); ++i) { |
| 445 DeoptimizeFunctionWithPreparedFunctionList( | 445 DeoptimizeFunctionWithPreparedFunctionList( |
| 446 JSFunction::cast(codes.at(i)->deoptimizing_functions())); | 446 JSFunction::cast(codes.at(i)->deoptimizing_functions())); |
| 447 codes.at(i)->set_deoptimizing_functions(undefined); | 447 codes.at(i)->set_deoptimizing_functions(undefined); |
| 448 } | 448 } |
| 449 } | 449 } |
| 450 | 450 |
| 451 | 451 |
| 452 void Deoptimizer::DeoptimizeAllFunctionsWith(Isolate* isolate, | 452 void Deoptimizer::DeoptimizeAllFunctionsWith(Isolate* isolate, |
| 453 OptimizedFunctionFilter* filter) { | 453 OptimizedFunctionFilter* filter) { |
| 454 AssertNoAllocation no_allocation; | 454 DisallowHeapAllocation no_allocation; |
| 455 | 455 |
| 456 // Run through the list of all native contexts and deoptimize. | 456 // Run through the list of all native contexts and deoptimize. |
| 457 Object* context = isolate->heap()->native_contexts_list(); | 457 Object* context = isolate->heap()->native_contexts_list(); |
| 458 while (!context->IsUndefined()) { | 458 while (!context->IsUndefined()) { |
| 459 DeoptimizeAllFunctionsForContext(Context::cast(context), filter); | 459 DeoptimizeAllFunctionsForContext(Context::cast(context), filter); |
| 460 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); | 460 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); |
| 461 } | 461 } |
| 462 } | 462 } |
| 463 | 463 |
| 464 | 464 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 int opt_count = function->shared()->opt_count(); | 551 int opt_count = function->shared()->opt_count(); |
| 552 if (opt_count > 0) opt_count--; | 552 if (opt_count > 0) opt_count--; |
| 553 function->shared()->set_opt_count(opt_count); | 553 function->shared()->set_opt_count(opt_count); |
| 554 } | 554 } |
| 555 } | 555 } |
| 556 compiled_code_ = FindOptimizedCode(function, optimized_code); | 556 compiled_code_ = FindOptimizedCode(function, optimized_code); |
| 557 StackFrame::Type frame_type = function == NULL | 557 StackFrame::Type frame_type = function == NULL |
| 558 ? StackFrame::STUB | 558 ? StackFrame::STUB |
| 559 : StackFrame::JAVA_SCRIPT; | 559 : StackFrame::JAVA_SCRIPT; |
| 560 trace_ = TraceEnabledFor(type, frame_type); | 560 trace_ = TraceEnabledFor(type, frame_type); |
| 561 ASSERT(HEAP->allow_allocation(false)); | 561 #ifdef DEBUG |
| 562 CHECK(AllowHeapAllocation::IsAllowed()); |
| 563 disallow_heap_allocation_ = new DisallowHeapAllocation(); |
| 564 #endif // DEBUG |
| 562 unsigned size = ComputeInputFrameSize(); | 565 unsigned size = ComputeInputFrameSize(); |
| 563 input_ = new(size) FrameDescription(size, function); | 566 input_ = new(size) FrameDescription(size, function); |
| 564 input_->SetFrameType(frame_type); | 567 input_->SetFrameType(frame_type); |
| 565 } | 568 } |
| 566 | 569 |
| 567 | 570 |
| 568 Code* Deoptimizer::FindOptimizedCode(JSFunction* function, | 571 Code* Deoptimizer::FindOptimizedCode(JSFunction* function, |
| 569 Code* optimized_code) { | 572 Code* optimized_code) { |
| 570 switch (bailout_type_) { | 573 switch (bailout_type_) { |
| 571 case Deoptimizer::SOFT: | 574 case Deoptimizer::SOFT: |
| (...skipping 29 matching lines...) Expand all Loading... |
| 601 if (function_->IsJSFunction()) { | 604 if (function_->IsJSFunction()) { |
| 602 function_->PrintName(); | 605 function_->PrintName(); |
| 603 } else { | 606 } else { |
| 604 PrintF("%s", Code::Kind2String(compiled_code_->kind())); | 607 PrintF("%s", Code::Kind2String(compiled_code_->kind())); |
| 605 } | 608 } |
| 606 } | 609 } |
| 607 | 610 |
| 608 | 611 |
| 609 Deoptimizer::~Deoptimizer() { | 612 Deoptimizer::~Deoptimizer() { |
| 610 ASSERT(input_ == NULL && output_ == NULL); | 613 ASSERT(input_ == NULL && output_ == NULL); |
| 614 ASSERT(disallow_heap_allocation_ == NULL); |
| 611 } | 615 } |
| 612 | 616 |
| 613 | 617 |
| 614 void Deoptimizer::DeleteFrameDescriptions() { | 618 void Deoptimizer::DeleteFrameDescriptions() { |
| 615 delete input_; | 619 delete input_; |
| 616 for (int i = 0; i < output_count_; ++i) { | 620 for (int i = 0; i < output_count_; ++i) { |
| 617 if (output_[i] != input_) delete output_[i]; | 621 if (output_[i] != input_) delete output_[i]; |
| 618 } | 622 } |
| 619 delete[] output_; | 623 delete[] output_; |
| 620 input_ = NULL; | 624 input_ = NULL; |
| 621 output_ = NULL; | 625 output_ = NULL; |
| 622 ASSERT(!HEAP->allow_allocation(true)); | 626 #ifdef DEBUG |
| 627 CHECK(!AllowHeapAllocation::IsAllowed()); |
| 628 CHECK(disallow_heap_allocation_ != NULL); |
| 629 delete disallow_heap_allocation_; |
| 630 disallow_heap_allocation_ = NULL; |
| 631 #endif // DEBUG |
| 623 } | 632 } |
| 624 | 633 |
| 625 | 634 |
| 626 Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate, | 635 Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate, |
| 627 int id, | 636 int id, |
| 628 BailoutType type, | 637 BailoutType type, |
| 629 GetEntryMode mode) { | 638 GetEntryMode mode) { |
| 630 ASSERT(id >= 0); | 639 ASSERT(id >= 0); |
| 631 if (id >= kMaxNumberOfEntries) return NULL; | 640 if (id >= kMaxNumberOfEntries) return NULL; |
| 632 if (mode == ENSURE_ENTRY_CODE) { | 641 if (mode == ENSURE_ENTRY_CODE) { |
| (...skipping 2215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2848 for (int i = 0; i < args_slots->length(); ++i) { | 2857 for (int i = 0; i < args_slots->length(); ++i) { |
| 2849 (*args_slots)[i] = ComputeSlotForNextArgument(it, data, frame); | 2858 (*args_slots)[i] = ComputeSlotForNextArgument(it, data, frame); |
| 2850 } | 2859 } |
| 2851 } | 2860 } |
| 2852 | 2861 |
| 2853 | 2862 |
| 2854 Vector<SlotRef> SlotRef::ComputeSlotMappingForArguments( | 2863 Vector<SlotRef> SlotRef::ComputeSlotMappingForArguments( |
| 2855 JavaScriptFrame* frame, | 2864 JavaScriptFrame* frame, |
| 2856 int inlined_jsframe_index, | 2865 int inlined_jsframe_index, |
| 2857 int formal_parameter_count) { | 2866 int formal_parameter_count) { |
| 2858 AssertNoAllocation no_gc; | 2867 DisallowHeapAllocation no_gc; |
| 2859 int deopt_index = Safepoint::kNoDeoptimizationIndex; | 2868 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
| 2860 DeoptimizationInputData* data = | 2869 DeoptimizationInputData* data = |
| 2861 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); | 2870 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); |
| 2862 TranslationIterator it(data->TranslationByteArray(), | 2871 TranslationIterator it(data->TranslationByteArray(), |
| 2863 data->TranslationIndex(deopt_index)->value()); | 2872 data->TranslationIndex(deopt_index)->value()); |
| 2864 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | 2873 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
| 2865 ASSERT(opcode == Translation::BEGIN); | 2874 ASSERT(opcode == Translation::BEGIN); |
| 2866 it.Next(); // Drop frame count. | 2875 it.Next(); // Drop frame count. |
| 2867 int jsframe_count = it.Next(); | 2876 int jsframe_count = it.Next(); |
| 2868 USE(jsframe_count); | 2877 USE(jsframe_count); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2950 | 2959 |
| 2951 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | 2960 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
| 2952 v->VisitPointer(BitCast<Object**>(&function_)); | 2961 v->VisitPointer(BitCast<Object**>(&function_)); |
| 2953 v->VisitPointers(parameters_, parameters_ + parameters_count_); | 2962 v->VisitPointers(parameters_, parameters_ + parameters_count_); |
| 2954 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | 2963 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
| 2955 } | 2964 } |
| 2956 | 2965 |
| 2957 #endif // ENABLE_DEBUGGER_SUPPORT | 2966 #endif // ENABLE_DEBUGGER_SUPPORT |
| 2958 | 2967 |
| 2959 } } // namespace v8::internal | 2968 } } // namespace v8::internal |
| OLD | NEW |