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 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
338 } | 338 } |
339 unsigned table_offset = cgen.EmitBackEdgeTable(); | 339 unsigned table_offset = cgen.EmitBackEdgeTable(); |
340 | 340 |
341 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); | 341 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); |
342 Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info); | 342 Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info); |
343 code->set_optimizable(info->IsOptimizable() && | 343 code->set_optimizable(info->IsOptimizable() && |
344 !info->function()->dont_optimize() && | 344 !info->function()->dont_optimize() && |
345 info->function()->scope()->AllowsLazyCompilation()); | 345 info->function()->scope()->AllowsLazyCompilation()); |
346 cgen.PopulateDeoptimizationData(code); | 346 cgen.PopulateDeoptimizationData(code); |
347 cgen.PopulateTypeFeedbackInfo(code); | 347 cgen.PopulateTypeFeedbackInfo(code); |
348 cgen.PopulateTypeFeedbackCells(code); | |
349 code->set_has_deoptimization_support(info->HasDeoptimizationSupport()); | 348 code->set_has_deoptimization_support(info->HasDeoptimizationSupport()); |
350 code->set_handler_table(*cgen.handler_table()); | 349 code->set_handler_table(*cgen.handler_table()); |
351 #ifdef ENABLE_DEBUGGER_SUPPORT | 350 #ifdef ENABLE_DEBUGGER_SUPPORT |
352 code->set_compiled_optimizable(info->IsOptimizable()); | 351 code->set_compiled_optimizable(info->IsOptimizable()); |
353 #endif // ENABLE_DEBUGGER_SUPPORT | 352 #endif // ENABLE_DEBUGGER_SUPPORT |
354 code->set_allow_osr_at_loop_nesting_level(0); | 353 code->set_allow_osr_at_loop_nesting_level(0); |
355 code->set_profiler_ticks(0); | 354 code->set_profiler_ticks(0); |
356 code->set_back_edge_table_offset(table_offset); | 355 code->set_back_edge_table_offset(table_offset); |
357 code->set_back_edges_patched_for_osr(false); | 356 code->set_back_edges_patched_for_osr(false); |
358 CodeGenerator::PrintCode(code, info); | 357 CodeGenerator::PrintCode(code, info); |
(...skipping 21 matching lines...) Expand all Loading... | |
380 __ dd(length); | 379 __ dd(length); |
381 for (unsigned i = 0; i < length; ++i) { | 380 for (unsigned i = 0; i < length; ++i) { |
382 __ dd(back_edges_[i].id.ToInt()); | 381 __ dd(back_edges_[i].id.ToInt()); |
383 __ dd(back_edges_[i].pc); | 382 __ dd(back_edges_[i].pc); |
384 __ dd(back_edges_[i].loop_depth); | 383 __ dd(back_edges_[i].loop_depth); |
385 } | 384 } |
386 return offset; | 385 return offset; |
387 } | 386 } |
388 | 387 |
389 | 388 |
389 void FullCodeGenerator::FeedbackVectorWrapper::Initialize( | |
390 Isolate* isolate, | |
391 int minimum_length, | |
392 int maximum_length) { | |
393 ASSERT_EQ(isolate->heap()->the_hole_value(), | |
394 *TypeFeedbackInfo::UninitializedSentinel(isolate)); | |
395 feedback_vector_ = isolate->factory()->NewFixedArrayWithHoles(minimum_length, | |
Benedikt Meurer
2014/01/24 11:29:54
As discussed offline: Please add an explanation he
mvstanton
2014/01/30 15:13:41
Changed to a new approach.
| |
396 TENURED); | |
397 maximum_length_ = maximum_length; | |
398 used_ = 0; | |
399 } | |
400 | |
401 | |
402 void FullCodeGenerator::FeedbackVectorWrapper::Visit( | |
403 Isolate* isolate, | |
404 AstNode* node) { | |
405 int new_used = node->ConsumeFeedbackSlots(isolate, used_); | |
406 if (new_used > used_) { | |
407 int old_vector_length = feedback_vector_->length(); | |
408 if (new_used > old_vector_length) { | |
409 int min_extra = new_used - old_vector_length; | |
410 int max_extra = maximum_length_ - old_vector_length; | |
411 int extra = Min(min_extra * 4, max_extra); | |
412 | |
413 if (FLAG_trace_type_feedback) { | |
414 PrintF("Growing vector (min, max, chosen) (%d, %d, %d)\n", | |
415 min_extra, max_extra, extra); | |
416 } | |
417 | |
418 // We must grow the vector, somewhere between [new_used, maximum_length_]. | |
419 Handle<FixedArray> new_array = isolate->factory()->CopySizeFixedArray( | |
420 feedback_vector_, | |
421 feedback_vector_->length() + extra, | |
422 TENURED); | |
423 *(feedback_vector_.location()) = *new_array; | |
424 | |
425 // Initialize the slots to undefined | |
426 for (int i = Max(0, old_vector_length - 1); | |
427 i < feedback_vector_->length(); | |
428 i++) { | |
429 feedback_vector_->set( | |
430 i, | |
431 *TypeFeedbackInfo::UninitializedSentinel(isolate), | |
432 SKIP_WRITE_BARRIER); | |
433 } | |
434 } | |
435 | |
436 used_ = new_used; | |
437 ASSERT(used_ <= feedback_vector_->length()); | |
438 } | |
439 } | |
440 | |
441 | |
442 void FullCodeGenerator::FeedbackVectorWrapper::Set( | |
443 int slot, | |
444 Handle<Object> object) { | |
445 ASSERT(feedback_vector_->length() > slot); | |
446 feedback_vector_->set(slot, *object); | |
447 } | |
448 | |
449 | |
450 void FullCodeGenerator::FeedbackVectorWrapper::Finalize(Isolate* isolate) { | |
451 ASSERT(used_ <= feedback_vector_->length()); | |
452 if (used_ < feedback_vector_->length()) { | |
453 if (FLAG_trace_type_feedback) { | |
454 PrintF("Allocated feedback vector: shrank %d to %d slots.\n", | |
455 feedback_vector_->length(), used_); | |
456 } | |
457 | |
458 if (used_ > 0) { | |
459 feedback_vector_->Shrink(used_); | |
460 } | |
461 } | |
462 } | |
463 | |
464 | |
390 void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) { | 465 void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) { |
391 // Fill in the deoptimization information. | 466 // Fill in the deoptimization information. |
392 ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty()); | 467 ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty()); |
393 if (!info_->HasDeoptimizationSupport()) return; | 468 if (!info_->HasDeoptimizationSupport()) return; |
394 int length = bailout_entries_.length(); | 469 int length = bailout_entries_.length(); |
395 Handle<DeoptimizationOutputData> data = isolate()->factory()-> | 470 Handle<DeoptimizationOutputData> data = isolate()->factory()-> |
396 NewDeoptimizationOutputData(length, TENURED); | 471 NewDeoptimizationOutputData(length, TENURED); |
397 for (int i = 0; i < length; i++) { | 472 for (int i = 0; i < length; i++) { |
398 data->SetAstId(i, bailout_entries_[i].id); | 473 data->SetAstId(i, bailout_entries_[i].id); |
399 data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state)); | 474 data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state)); |
400 } | 475 } |
401 code->set_deoptimization_data(*data); | 476 code->set_deoptimization_data(*data); |
402 } | 477 } |
403 | 478 |
404 | 479 |
405 void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) { | 480 void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) { |
406 Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo(); | 481 Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo(); |
407 info->set_ic_total_count(ic_total_count_); | 482 info->set_ic_total_count(ic_total_count_); |
483 info->set_feedback_vector(*FeedbackVector()); | |
408 ASSERT(!isolate()->heap()->InNewSpace(*info)); | 484 ASSERT(!isolate()->heap()->InNewSpace(*info)); |
409 code->set_type_feedback_info(*info); | 485 code->set_type_feedback_info(*info); |
410 } | 486 } |
411 | 487 |
412 | 488 |
413 void FullCodeGenerator::Initialize() { | 489 void FullCodeGenerator::Initialize() { |
414 // The generation of debug code must match between the snapshot code and the | 490 // The generation of debug code must match between the snapshot code and the |
415 // code that is generated later. This is assumed by the debugger when it is | 491 // code that is generated later. This is assumed by the debugger when it is |
416 // calculating PC offsets after generating a debug version of code. Therefore | 492 // calculating PC offsets after generating a debug version of code. Therefore |
417 // we disable the production of debug code in the full compiler if we are | 493 // we disable the production of debug code in the full compiler if we are |
418 // either generating a snapshot or we booted from a snapshot. | 494 // either generating a snapshot or we booted from a snapshot. |
419 generate_debug_code_ = FLAG_debug_code && | 495 generate_debug_code_ = FLAG_debug_code && |
420 !Serializer::enabled() && | 496 !Serializer::enabled() && |
421 !Snapshot::HaveASnapshotToStartFrom(); | 497 !Snapshot::HaveASnapshotToStartFrom(); |
422 masm_->set_emit_debug_code(generate_debug_code_); | 498 masm_->set_emit_debug_code(generate_debug_code_); |
423 masm_->set_predictable_code_size(true); | 499 masm_->set_predictable_code_size(true); |
424 InitializeAstVisitor(info_->zone()); | 500 InitializeAstVisitor(info_->zone()); |
425 } | 501 } |
426 | 502 |
427 | 503 |
428 void FullCodeGenerator::PopulateTypeFeedbackCells(Handle<Code> code) { | |
429 if (type_feedback_cells_.is_empty()) return; | |
430 int length = type_feedback_cells_.length(); | |
431 int array_size = TypeFeedbackCells::LengthOfFixedArray(length); | |
432 Handle<TypeFeedbackCells> cache = Handle<TypeFeedbackCells>::cast( | |
433 isolate()->factory()->NewFixedArray(array_size, TENURED)); | |
434 for (int i = 0; i < length; i++) { | |
435 cache->SetAstId(i, type_feedback_cells_[i].ast_id); | |
436 cache->SetCell(i, *type_feedback_cells_[i].cell); | |
437 } | |
438 TypeFeedbackInfo::cast(code->type_feedback_info())->set_type_feedback_cells( | |
439 *cache); | |
440 } | |
441 | |
442 | |
443 void FullCodeGenerator::PrepareForBailout(Expression* node, State state) { | 504 void FullCodeGenerator::PrepareForBailout(Expression* node, State state) { |
444 PrepareForBailoutForId(node->id(), state); | 505 PrepareForBailoutForId(node->id(), state); |
445 } | 506 } |
446 | 507 |
447 | 508 |
448 void FullCodeGenerator::CallLoadIC(ContextualMode mode, TypeFeedbackId id) { | 509 void FullCodeGenerator::CallLoadIC(ContextualMode mode, TypeFeedbackId id) { |
449 Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode); | 510 Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode); |
450 CallIC(ic, mode, id); | 511 CallIC(ic, mode, id); |
451 } | 512 } |
452 | 513 |
(...skipping 28 matching lines...) Expand all Loading... | |
481 unsigned pc_and_state = | 542 unsigned pc_and_state = |
482 StateField::encode(state) | PcField::encode(masm_->pc_offset()); | 543 StateField::encode(state) | PcField::encode(masm_->pc_offset()); |
483 ASSERT(Smi::IsValid(pc_and_state)); | 544 ASSERT(Smi::IsValid(pc_and_state)); |
484 BailoutEntry entry = { id, pc_and_state }; | 545 BailoutEntry entry = { id, pc_and_state }; |
485 ASSERT(!prepared_bailout_ids_.Contains(id.ToInt())); | 546 ASSERT(!prepared_bailout_ids_.Contains(id.ToInt())); |
486 prepared_bailout_ids_.Add(id.ToInt(), zone()); | 547 prepared_bailout_ids_.Add(id.ToInt(), zone()); |
487 bailout_entries_.Add(entry, zone()); | 548 bailout_entries_.Add(entry, zone()); |
488 } | 549 } |
489 | 550 |
490 | 551 |
491 void FullCodeGenerator::RecordTypeFeedbackCell( | |
492 TypeFeedbackId id, Handle<Cell> cell) { | |
493 TypeFeedbackCellEntry entry = { id, cell }; | |
494 type_feedback_cells_.Add(entry, zone()); | |
495 } | |
496 | |
497 | |
498 void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) { | 552 void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) { |
499 // The pc offset does not need to be encoded and packed together with a state. | 553 // The pc offset does not need to be encoded and packed together with a state. |
500 ASSERT(masm_->pc_offset() > 0); | 554 ASSERT(masm_->pc_offset() > 0); |
501 ASSERT(loop_depth() > 0); | 555 ASSERT(loop_depth() > 0); |
502 uint8_t depth = Min(loop_depth(), Code::kMaxLoopNestingMarker); | 556 uint8_t depth = Min(loop_depth(), Code::kMaxLoopNestingMarker); |
503 BackEdgeEntry entry = | 557 BackEdgeEntry entry = |
504 { ast_id, static_cast<unsigned>(masm_->pc_offset()), depth }; | 558 { ast_id, static_cast<unsigned>(masm_->pc_offset()), depth }; |
505 back_edges_.Add(entry, zone()); | 559 back_edges_.Add(entry, zone()); |
506 } | 560 } |
507 | 561 |
(...skipping 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1746 } | 1800 } |
1747 return true; | 1801 return true; |
1748 } | 1802 } |
1749 #endif // DEBUG | 1803 #endif // DEBUG |
1750 | 1804 |
1751 | 1805 |
1752 #undef __ | 1806 #undef __ |
1753 | 1807 |
1754 | 1808 |
1755 } } // namespace v8::internal | 1809 } } // namespace v8::internal |
OLD | NEW |