Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/deoptimizer.cc

Issue 19638014: Factor out common code from platform-specific deoptimization. Fix Deoptimizer not to need to partit… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Cleanups post-review. Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/deoptimizer.h ('k') | src/ia32/deoptimizer-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 // Run through the list of all native contexts and deoptimize. 324 // Run through the list of all native contexts and deoptimize.
325 Object* context = isolate->heap()->native_contexts_list(); 325 Object* context = isolate->heap()->native_contexts_list();
326 while (!context->IsUndefined()) { 326 while (!context->IsUndefined()) {
327 VisitAllOptimizedFunctionsForContext(Context::cast(context), visitor); 327 VisitAllOptimizedFunctionsForContext(Context::cast(context), visitor);
328 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); 328 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
329 } 329 }
330 } 330 }
331 331
332 332
333 // Removes the functions selected by the given filter from the optimized 333 // Removes the functions selected by the given filter from the optimized
334 // function list of the given context and partitions the removed functions 334 // function list of the given context and adds their code to the list of
335 // into one or more lists such that all functions in a list share the same 335 // code objects to be deoptimized.
336 // code. The head of each list is written in the deoptimizing_functions field 336 static void SelectCodeToDeoptimize(Context* context,
337 // of the corresponding code object. 337 OptimizedFunctionFilter* filter,
338 // The found code objects are returned in the given zone list. 338 ZoneList<Code*>* codes,
339 static void PartitionOptimizedFunctions(Context* context, 339 Zone* zone,
340 OptimizedFunctionFilter* filter, 340 Object* undefined) {
341 ZoneList<Code*>* partitions,
342 Zone* zone,
343 Object* undefined) {
344 DisallowHeapAllocation no_allocation; 341 DisallowHeapAllocation no_allocation;
345 Object* current = context->get(Context::OPTIMIZED_FUNCTIONS_LIST); 342 Object* current = context->get(Context::OPTIMIZED_FUNCTIONS_LIST);
346 Object* remainder_head = undefined; 343 Object* remainder_head = undefined;
347 Object* remainder_tail = undefined; 344 Object* remainder_tail = undefined;
348 ASSERT_EQ(0, partitions->length()); 345
346 // TODO(titzer): rewrite to not modify unselected functions.
349 while (current != undefined) { 347 while (current != undefined) {
350 JSFunction* function = JSFunction::cast(current); 348 JSFunction* function = JSFunction::cast(current);
351 current = function->next_function_link(); 349 current = function->next_function_link();
352 if (filter->TakeFunction(function)) { 350 if (filter->TakeFunction(function)) {
351 // Extract this function from the context's list and remember the code.
353 Code* code = function->code(); 352 Code* code = function->code();
354 if (code->deoptimizing_functions() == undefined) { 353 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
355 partitions->Add(code, zone); 354 if (code->marked_for_deoptimization()) {
355 ASSERT(codes->Contains(code));
356 } else { 356 } else {
357 ASSERT(partitions->Contains(code)); 357 code->set_marked_for_deoptimization(true);
358 codes->Add(code, zone);
358 } 359 }
359 function->set_next_function_link(code->deoptimizing_functions()); 360 SharedFunctionInfo* shared = function->shared();
360 code->set_deoptimizing_functions(function); 361 // Replace the function's code with the shared code.
362 function->set_code(shared->code());
363 // Evict the code from the optimized code map.
364 shared->EvictFromOptimizedCodeMap(code, "deoptimized function");
365 // Remove the function from the optimized functions list.
366 function->set_next_function_link(undefined);
367
368 if (FLAG_trace_deopt) {
369 PrintF("[forced deoptimization: ");
370 function->PrintName();
371 PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
372 }
361 } else { 373 } else {
374 // Don't select this function; link it back into the list.
362 if (remainder_head == undefined) { 375 if (remainder_head == undefined) {
363 remainder_head = function; 376 remainder_head = function;
364 } else { 377 } else {
365 JSFunction::cast(remainder_tail)->set_next_function_link(function); 378 JSFunction::cast(remainder_tail)->set_next_function_link(function);
366 } 379 }
367 remainder_tail = function; 380 remainder_tail = function;
368 } 381 }
369 } 382 }
370 if (remainder_tail != undefined) { 383 if (remainder_tail != undefined) {
371 JSFunction::cast(remainder_tail)->set_next_function_link(undefined); 384 JSFunction::cast(remainder_tail)->set_next_function_link(undefined);
(...skipping 14 matching lines...) Expand all
386 public: 399 public:
387 explicit DeoptimizeWithMatchingCodeFilter(Code* code) : code_(code) {} 400 explicit DeoptimizeWithMatchingCodeFilter(Code* code) : code_(code) {}
388 virtual bool TakeFunction(JSFunction* function) { 401 virtual bool TakeFunction(JSFunction* function) {
389 return function->code() == code_; 402 return function->code() == code_;
390 } 403 }
391 private: 404 private:
392 Code* code_; 405 Code* code_;
393 }; 406 };
394 407
395 408
409 class DeoptimizeMarkedCodeFilter : public OptimizedFunctionFilter {
410 public:
411 virtual bool TakeFunction(JSFunction* function) {
412 return function->code()->marked_for_deoptimization();
413 }
414 };
415
416
396 void Deoptimizer::DeoptimizeAll(Isolate* isolate) { 417 void Deoptimizer::DeoptimizeAll(Isolate* isolate) {
397 DisallowHeapAllocation no_allocation; 418 DisallowHeapAllocation no_allocation;
398 419
399 if (FLAG_trace_deopt) { 420 if (FLAG_trace_deopt) {
400 PrintF("[deoptimize all contexts]\n"); 421 PrintF("[deoptimize all contexts]\n");
401 } 422 }
402 423
403 DeoptimizeAllFilter filter; 424 DeoptimizeAllFilter filter;
404 DeoptimizeAllFunctionsWith(isolate, &filter); 425 DeoptimizeAllFunctionsWith(isolate, &filter);
405 } 426 }
406 427
407 428
408 void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) { 429 void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) {
409 DisallowHeapAllocation no_allocation; 430 DisallowHeapAllocation no_allocation;
410 DeoptimizeAllFilter filter; 431 DeoptimizeAllFilter filter;
411 if (object->IsJSGlobalProxy()) { 432 if (object->IsJSGlobalProxy()) {
412 Object* proto = object->GetPrototype(); 433 Object* proto = object->GetPrototype();
413 ASSERT(proto->IsJSGlobalObject()); 434 ASSERT(proto->IsJSGlobalObject());
414 DeoptimizeAllFunctionsForContext( 435 DeoptimizeAllFunctionsForContext(
415 GlobalObject::cast(proto)->native_context(), &filter); 436 GlobalObject::cast(proto)->native_context(), &filter);
416 } else if (object->IsGlobalObject()) { 437 } else if (object->IsGlobalObject()) {
417 DeoptimizeAllFunctionsForContext( 438 DeoptimizeAllFunctionsForContext(
418 GlobalObject::cast(object)->native_context(), &filter); 439 GlobalObject::cast(object)->native_context(), &filter);
419 } 440 }
420 } 441 }
421 442
422 443
423 void Deoptimizer::DeoptimizeFunction(JSFunction* function) { 444 void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
424 if (!function->IsOptimized()) return;
425 Code* code = function->code(); 445 Code* code = function->code();
426 Context* context = function->context()->native_context(); 446 if (code->kind() != Code::OPTIMIZED_FUNCTION) return;
427 Isolate* isolate = context->GetIsolate();
428 Object* undefined = isolate->heap()->undefined_value();
429 Zone zone(isolate);
430 ZoneList<Code*> codes(1, &zone);
431 DeoptimizeWithMatchingCodeFilter filter(code); 447 DeoptimizeWithMatchingCodeFilter filter(code);
432 PartitionOptimizedFunctions(context, &filter, &codes, &zone, undefined); 448 DeoptimizeAllFunctionsForContext(
433 ASSERT_EQ(1, codes.length()); 449 function->context()->native_context(), &filter);
434 DeoptimizeFunctionWithPreparedFunctionList(
435 JSFunction::cast(codes.at(0)->deoptimizing_functions()));
436 codes.at(0)->set_deoptimizing_functions(undefined);
437 } 450 }
438 451
439 452
440 void Deoptimizer::DeoptimizeAllFunctionsForContext( 453 void Deoptimizer::DeoptimizeAllFunctionsForContext(
441 Context* context, OptimizedFunctionFilter* filter) { 454 Context* context, OptimizedFunctionFilter* filter) {
442 ASSERT(context->IsNativeContext()); 455 ASSERT(context->IsNativeContext());
443 Isolate* isolate = context->GetIsolate(); 456 Isolate* isolate = context->GetIsolate();
444 Object* undefined = isolate->heap()->undefined_value(); 457 Object* undefined = isolate->heap()->undefined_value();
445 Zone zone(isolate); 458 Zone zone(isolate);
446 ZoneList<Code*> codes(1, &zone); 459 ZoneList<Code*> codes(4, &zone);
447 PartitionOptimizedFunctions(context, filter, &codes, &zone, undefined); 460 SelectCodeToDeoptimize(context, filter, &codes, &zone, undefined);
448 for (int i = 0; i < codes.length(); ++i) { 461 for (int i = 0; i < codes.length(); i++) {
449 DeoptimizeFunctionWithPreparedFunctionList( 462 DeoptimizeCode(isolate, codes.at(i));
450 JSFunction::cast(codes.at(i)->deoptimizing_functions()));
451 codes.at(i)->set_deoptimizing_functions(undefined);
452 } 463 }
453 } 464 }
454 465
455 466
456 void Deoptimizer::DeoptimizeAllFunctionsWith(Isolate* isolate, 467 void Deoptimizer::DeoptimizeAllFunctionsWith(Isolate* isolate,
457 OptimizedFunctionFilter* filter) { 468 OptimizedFunctionFilter* filter) {
458 DisallowHeapAllocation no_allocation; 469 DisallowHeapAllocation no_allocation;
459 470
460 // Run through the list of all native contexts and deoptimize. 471 // Run through the list of all native contexts and deoptimize.
461 Object* context = isolate->heap()->native_contexts_list(); 472 Object* context = isolate->heap()->native_contexts_list();
462 while (!context->IsUndefined()) { 473 while (!context->IsUndefined()) {
463 DeoptimizeAllFunctionsForContext(Context::cast(context), filter); 474 DeoptimizeAllFunctionsForContext(Context::cast(context), filter);
464 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); 475 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
465 } 476 }
466 } 477 }
467 478
468 479
480 void Deoptimizer::DeoptimizeCodeList(Isolate* isolate, ZoneList<Code*>* codes) {
481 if (codes->length() == 0) return; // Nothing to do.
482
483 // Mark the code; any functions refering to this code will be selected.
484 for (int i = 0; i < codes->length(); i++) {
485 ASSERT(!codes->at(i)->marked_for_deoptimization());
486 codes->at(i)->set_marked_for_deoptimization(true);
487 }
488
489 // For all contexts, remove optimized functions that refer to the selected
490 // code from the optimized function lists.
491 Object* undefined = isolate->heap()->undefined_value();
492 Zone zone(isolate);
493 Object* list = isolate->heap()->native_contexts_list();
494 DeoptimizeMarkedCodeFilter filter;
495 while (!list->IsUndefined()) {
496 Context* context = Context::cast(list);
497 // Note that selecting code unlinks the functions that refer to it.
498 SelectCodeToDeoptimize(context, &filter, codes, &zone, undefined);
499 list = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
500 }
501
502 // Now deoptimize all the code.
503 for (int i = 0; i < codes->length(); i++) {
504 DeoptimizeCode(isolate, codes->at(i));
505 }
506 }
507
508
509 void Deoptimizer::DeoptimizeCode(Isolate* isolate, Code* code) {
510 HandleScope scope(isolate);
511 DisallowHeapAllocation nha;
512
513 // Do platform-specific patching of the optimized code.
514 PatchCodeForDeoptimization(isolate, code);
515
516 // Add the deoptimizing code to the list.
517 DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code);
518 DeoptimizerData* data = isolate->deoptimizer_data();
519 node->set_next(data->deoptimizing_code_list_);
520 data->deoptimizing_code_list_ = node;
521
522 // We might be in the middle of incremental marking with compaction.
523 // Tell collector to treat this code object in a special way and
524 // ignore all slots that might have been recorded on it.
525 isolate->heap()->mark_compact_collector()->InvalidateCode(code);
526 }
527
528
469 void Deoptimizer::HandleWeakDeoptimizedCode(v8::Isolate* isolate, 529 void Deoptimizer::HandleWeakDeoptimizedCode(v8::Isolate* isolate,
470 v8::Persistent<v8::Value>* obj, 530 v8::Persistent<v8::Value>* obj,
471 void* parameter) { 531 void* parameter) {
472 DeoptimizingCodeListNode* node = 532 DeoptimizingCodeListNode* node =
473 reinterpret_cast<DeoptimizingCodeListNode*>(parameter); 533 reinterpret_cast<DeoptimizingCodeListNode*>(parameter);
474 DeoptimizerData* data = 534 DeoptimizerData* data =
475 reinterpret_cast<Isolate*>(isolate)->deoptimizer_data(); 535 reinterpret_cast<Isolate*>(isolate)->deoptimizer_data();
476 data->RemoveDeoptimizingCode(*node->code()); 536 data->RemoveDeoptimizingCode(*node->code());
477 #ifdef DEBUG 537 #ifdef DEBUG
478 for (DeoptimizingCodeListNode* current = data->deoptimizing_code_list_; 538 for (DeoptimizingCodeListNode* current = data->deoptimizing_code_list_;
(...skipping 2083 matching lines...) Expand 10 before | Expand all | Expand 10 after
2562 desc.instr_size); 2622 desc.instr_size);
2563 chunk->CommitArea(desc.instr_size); 2623 chunk->CommitArea(desc.instr_size);
2564 CopyBytes(chunk->area_start(), desc.buffer, 2624 CopyBytes(chunk->area_start(), desc.buffer,
2565 static_cast<size_t>(desc.instr_size)); 2625 static_cast<size_t>(desc.instr_size));
2566 CPU::FlushICache(chunk->area_start(), desc.instr_size); 2626 CPU::FlushICache(chunk->area_start(), desc.instr_size);
2567 2627
2568 data->deopt_entry_code_entries_[type] = entry_count; 2628 data->deopt_entry_code_entries_[type] = entry_count;
2569 } 2629 }
2570 2630
2571 2631
2572 void Deoptimizer::ReplaceCodeForRelatedFunctions(JSFunction* function,
2573 Code* code) {
2574 SharedFunctionInfo* shared = function->shared();
2575 Object* undefined = function->GetHeap()->undefined_value();
2576 Object* current = function;
2577
2578 while (current != undefined) {
2579 JSFunction* func = JSFunction::cast(current);
2580 current = func->next_function_link();
2581 func->set_code(shared->code());
2582 func->set_next_function_link(undefined);
2583 }
2584 }
2585
2586
2587 FrameDescription::FrameDescription(uint32_t frame_size, 2632 FrameDescription::FrameDescription(uint32_t frame_size,
2588 JSFunction* function) 2633 JSFunction* function)
2589 : frame_size_(frame_size), 2634 : frame_size_(frame_size),
2590 function_(function), 2635 function_(function),
2591 top_(kZapUint32), 2636 top_(kZapUint32),
2592 pc_(kZapUint32), 2637 pc_(kZapUint32),
2593 fp_(kZapUint32), 2638 fp_(kZapUint32),
2594 context_(kZapUint32) { 2639 context_(kZapUint32) {
2595 // Zap all the registers. 2640 // Zap all the registers.
2596 for (int r = 0; r < Register::kNumRegisters; r++) { 2641 for (int r = 0; r < Register::kNumRegisters; r++) {
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after
3096 3141
3097 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { 3142 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) {
3098 v->VisitPointer(BitCast<Object**>(&function_)); 3143 v->VisitPointer(BitCast<Object**>(&function_));
3099 v->VisitPointers(parameters_, parameters_ + parameters_count_); 3144 v->VisitPointers(parameters_, parameters_ + parameters_count_);
3100 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); 3145 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
3101 } 3146 }
3102 3147
3103 #endif // ENABLE_DEBUGGER_SUPPORT 3148 #endif // ENABLE_DEBUGGER_SUPPORT
3104 3149
3105 } } // namespace v8::internal 3150 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/deoptimizer.h ('k') | src/ia32/deoptimizer-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698