diff options
Diffstat (limited to 'chromium/v8/src/full-codegen.cc')
-rw-r--r-- | chromium/v8/src/full-codegen.cc | 215 |
1 files changed, 90 insertions, 125 deletions
diff --git a/chromium/v8/src/full-codegen.cc b/chromium/v8/src/full-codegen.cc index 483d1e378d4..0c82eb3d82b 100644 --- a/chromium/v8/src/full-codegen.cc +++ b/chromium/v8/src/full-codegen.cc @@ -1,43 +1,20 @@ // Copyright 2012 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "v8.h" - -#include "codegen.h" -#include "compiler.h" -#include "debug.h" -#include "full-codegen.h" -#include "liveedit.h" -#include "macro-assembler.h" -#include "prettyprinter.h" -#include "scopes.h" -#include "scopeinfo.h" -#include "snapshot.h" -#include "stub-cache.h" +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/v8.h" + +#include "src/codegen.h" +#include "src/compiler.h" +#include "src/debug.h" +#include "src/full-codegen.h" +#include "src/liveedit.h" +#include "src/macro-assembler.h" +#include "src/prettyprinter.h" +#include "src/scopes.h" +#include "src/scopeinfo.h" +#include "src/snapshot.h" +#include "src/stub-cache.h" namespace v8 { namespace internal { @@ -312,6 +289,10 @@ void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) { bool FullCodeGenerator::MakeCode(CompilationInfo* info) { Isolate* isolate = info->isolate(); + + Logger::TimerEventScope timer( + isolate, Logger::TimerEventScope::v8_compile_full_code); + Handle<Script> script = info->script(); if (!script->IsUndefined() && !script->source()->IsUndefined()) { int len = String::cast(script->source())->length(); @@ -341,12 +322,9 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) { info->function()->scope()->AllowsLazyCompilation()); cgen.PopulateDeoptimizationData(code); cgen.PopulateTypeFeedbackInfo(code); - cgen.PopulateTypeFeedbackCells(code); code->set_has_deoptimization_support(info->HasDeoptimizationSupport()); code->set_handler_table(*cgen.handler_table()); -#ifdef ENABLE_DEBUGGER_SUPPORT code->set_compiled_optimizable(info->IsOptimizable()); -#endif // ENABLE_DEBUGGER_SUPPORT code->set_allow_osr_at_loop_nesting_level(0); code->set_profiler_ticks(0); code->set_back_edge_table_offset(table_offset); @@ -383,13 +361,23 @@ unsigned FullCodeGenerator::EmitBackEdgeTable() { } +void FullCodeGenerator::EnsureSlotContainsAllocationSite(int slot) { + Handle<FixedArray> vector = FeedbackVector(); + if (!vector->get(slot)->IsAllocationSite()) { + Handle<AllocationSite> allocation_site = + isolate()->factory()->NewAllocationSite(); + vector->set(slot, *allocation_site); + } +} + + void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) { // Fill in the deoptimization information. ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty()); if (!info_->HasDeoptimizationSupport()) return; int length = bailout_entries_.length(); - Handle<DeoptimizationOutputData> data = isolate()->factory()-> - NewDeoptimizationOutputData(length, TENURED); + Handle<DeoptimizationOutputData> data = + DeoptimizationOutputData::New(isolate(), length, TENURED); for (int i = 0; i < length; i++) { data->SetAstId(i, bailout_entries_[i].id); data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state)); @@ -407,38 +395,36 @@ void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) { void FullCodeGenerator::Initialize() { + InitializeAstVisitor(info_->zone()); // The generation of debug code must match between the snapshot code and the // code that is generated later. This is assumed by the debugger when it is // calculating PC offsets after generating a debug version of code. Therefore // we disable the production of debug code in the full compiler if we are // either generating a snapshot or we booted from a snapshot. generate_debug_code_ = FLAG_debug_code && - !Serializer::enabled() && + !masm_->serializer_enabled() && !Snapshot::HaveASnapshotToStartFrom(); masm_->set_emit_debug_code(generate_debug_code_); masm_->set_predictable_code_size(true); - InitializeAstVisitor(info_->isolate()); } -void FullCodeGenerator::PopulateTypeFeedbackCells(Handle<Code> code) { - if (type_feedback_cells_.is_empty()) return; - int length = type_feedback_cells_.length(); - int array_size = TypeFeedbackCells::LengthOfFixedArray(length); - Handle<TypeFeedbackCells> cache = Handle<TypeFeedbackCells>::cast( - isolate()->factory()->NewFixedArray(array_size, TENURED)); - for (int i = 0; i < length; i++) { - cache->SetAstId(i, type_feedback_cells_[i].ast_id); - cache->SetCell(i, *type_feedback_cells_[i].cell); - } - TypeFeedbackInfo::cast(code->type_feedback_info())->set_type_feedback_cells( - *cache); +void FullCodeGenerator::PrepareForBailout(Expression* node, State state) { + PrepareForBailoutForId(node->id(), state); } +void FullCodeGenerator::CallLoadIC(ContextualMode contextual_mode, + TypeFeedbackId id) { + ExtraICState extra_state = LoadIC::ComputeExtraICState(contextual_mode); + Handle<Code> ic = LoadIC::initialize_stub(isolate(), extra_state); + CallIC(ic, id); +} + -void FullCodeGenerator::PrepareForBailout(Expression* node, State state) { - PrepareForBailoutForId(node->id(), state); +void FullCodeGenerator::CallStoreIC(TypeFeedbackId id) { + Handle<Code> ic = StoreIC::initialize_stub(isolate(), strict_mode()); + CallIC(ic, id); } @@ -466,20 +452,16 @@ void FullCodeGenerator::PrepareForBailoutForId(BailoutId id, State state) { unsigned pc_and_state = StateField::encode(state) | PcField::encode(masm_->pc_offset()); ASSERT(Smi::IsValid(pc_and_state)); +#ifdef DEBUG + for (int i = 0; i < bailout_entries_.length(); ++i) { + ASSERT(bailout_entries_[i].id != id); + } +#endif BailoutEntry entry = { id, pc_and_state }; - ASSERT(!prepared_bailout_ids_.Contains(id.ToInt())); - prepared_bailout_ids_.Add(id.ToInt(), zone()); bailout_entries_.Add(entry, zone()); } -void FullCodeGenerator::RecordTypeFeedbackCell( - TypeFeedbackId id, Handle<Cell> cell) { - TypeFeedbackCellEntry entry = { id, cell }; - type_feedback_cells_.Add(entry, zone()); -} - - void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) { // The pc offset does not need to be encoded and packed together with a state. ASSERT(masm_->pc_offset() > 0); @@ -617,7 +599,7 @@ void FullCodeGenerator::AllocateModules(ZoneList<Declaration*>* declarations) { ASSERT(scope->interface()->Index() >= 0); __ Push(Smi::FromInt(scope->interface()->Index())); __ Push(scope->GetScopeInfo()); - __ CallRuntime(Runtime::kPushModuleContext, 2); + __ CallRuntime(Runtime::kHiddenPushModuleContext, 2); StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); @@ -757,7 +739,7 @@ void FullCodeGenerator::VisitModuleLiteral(ModuleLiteral* module) { ASSERT(interface->Index() >= 0); __ Push(Smi::FromInt(interface->Index())); __ Push(Smi::FromInt(0)); - __ CallRuntime(Runtime::kPushModuleContext, 2); + __ CallRuntime(Runtime::kHiddenPushModuleContext, 2); StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); { @@ -808,10 +790,10 @@ void FullCodeGenerator::VisitModuleUrl(ModuleUrl* module) { int FullCodeGenerator::DeclareGlobalsFlags() { - ASSERT(DeclareGlobalsLanguageMode::is_valid(language_mode())); + ASSERT(DeclareGlobalsStrictMode::is_valid(strict_mode())); return DeclareGlobalsEvalFlag::encode(is_eval()) | DeclareGlobalsNativeFlag::encode(is_native()) | - DeclareGlobalsLanguageMode::encode(language_mode()); + DeclareGlobalsStrictMode::encode(strict_mode()); } @@ -826,13 +808,12 @@ void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) { void FullCodeGenerator::SetStatementPosition(Statement* stmt) { -#ifdef ENABLE_DEBUGGER_SUPPORT - if (!isolate()->debugger()->IsDebuggerActive()) { + if (!info_->is_debug()) { CodeGenerator::RecordPositions(masm_, stmt->position()); } else { // Check if the statement will be breakable without adding a debug break // slot. - BreakableStatementChecker checker(isolate()); + BreakableStatementChecker checker(zone()); checker.Check(stmt); // Record the statement position right here if the statement is not // breakable. For breakable statements the actual recording of the @@ -842,23 +823,19 @@ void FullCodeGenerator::SetStatementPosition(Statement* stmt) { // If the position recording did record a new position generate a debug // break slot to make the statement breakable. if (position_recorded) { - Debug::GenerateSlot(masm_); + DebugCodegen::GenerateSlot(masm_); } } -#else - CodeGenerator::RecordPositions(masm_, stmt->position()); -#endif } void FullCodeGenerator::SetExpressionPosition(Expression* expr) { -#ifdef ENABLE_DEBUGGER_SUPPORT - if (!isolate()->debugger()->IsDebuggerActive()) { + if (!info_->is_debug()) { CodeGenerator::RecordPositions(masm_, expr->position()); } else { // Check if the expression will be breakable without adding a debug break // slot. - BreakableStatementChecker checker(isolate()); + BreakableStatementChecker checker(zone()); checker.Check(expr); // Record a statement position right here if the expression is not // breakable. For breakable expressions the actual recording of the @@ -872,12 +849,9 @@ void FullCodeGenerator::SetExpressionPosition(Expression* expr) { // If the position recording did record a new position generate a debug // break slot to make the statement breakable. if (position_recorded) { - Debug::GenerateSlot(masm_); + DebugCodegen::GenerateSlot(masm_); } } -#else - CodeGenerator::RecordPositions(masm_, pos); -#endif } @@ -901,7 +875,6 @@ void FullCodeGenerator::SetSourcePosition(int pos) { const FullCodeGenerator::InlineFunctionGenerator FullCodeGenerator::kInlineFunctionGenerators[] = { INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) - INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) }; #undef INLINE_FUNCTION_GENERATOR_ADDRESS @@ -1079,35 +1052,30 @@ void FullCodeGenerator::VisitBlock(Block* stmt) { Scope* saved_scope = scope(); // Push a block context when entering a block with block scoped variables. - if (stmt->scope() != NULL) { + if (stmt->scope() == NULL) { + PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); + } else { scope_ = stmt->scope(); ASSERT(!scope_->is_module_scope()); { Comment cmnt(masm_, "[ Extend block context"); - Handle<ScopeInfo> scope_info = scope_->GetScopeInfo(); - int heap_slots = scope_info->ContextLength() - Context::MIN_CONTEXT_SLOTS; - __ Push(scope_info); + __ Push(scope_->GetScopeInfo()); PushFunctionArgumentForContextAllocation(); - if (heap_slots <= FastNewBlockContextStub::kMaximumSlots) { - FastNewBlockContextStub stub(heap_slots); - __ CallStub(&stub); - } else { - __ CallRuntime(Runtime::kPushBlockContext, 2); - } + __ CallRuntime(Runtime::kHiddenPushBlockContext, 2); // Replace the context stored in the frame. StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); + PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); } { Comment cmnt(masm_, "[ Declarations"); VisitDeclarations(scope_->declarations()); + PrepareForBailoutForId(stmt->DeclsId(), NO_REGISTERS); } } - PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); VisitStatements(stmt->statements()); scope_ = saved_scope; __ bind(nested_block.break_label()); - PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); // Pop block context if necessary. if (stmt->scope() != NULL) { @@ -1116,6 +1084,7 @@ void FullCodeGenerator::VisitBlock(Block* stmt) { StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); } + PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); } @@ -1124,7 +1093,7 @@ void FullCodeGenerator::VisitModuleStatement(ModuleStatement* stmt) { __ Push(Smi::FromInt(stmt->proxy()->interface()->Index())); __ Push(Smi::FromInt(0)); - __ CallRuntime(Runtime::kPushModuleContext, 2); + __ CallRuntime(Runtime::kHiddenPushModuleContext, 2); StoreToFrameField( StandardFrameConstants::kContextOffset, context_register()); @@ -1263,7 +1232,7 @@ void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) { VisitForStackValue(stmt->expression()); PushFunctionArgumentForContextAllocation(); - __ CallRuntime(Runtime::kPushWithContext, 2); + __ CallRuntime(Runtime::kHiddenPushWithContext, 2); StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); Scope* saved_scope = scope(); @@ -1416,7 +1385,7 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { __ Push(stmt->variable()->name()); __ Push(result_register()); PushFunctionArgumentForContextAllocation(); - __ CallRuntime(Runtime::kPushCatchContext, 3); + __ CallRuntime(Runtime::kHiddenPushCatchContext, 3); StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); } @@ -1480,7 +1449,7 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { // rethrow the exception if it returns. __ Call(&finally_entry); __ Push(result_register()); - __ CallRuntime(Runtime::kReThrow, 1); + __ CallRuntime(Runtime::kHiddenReThrow, 1); // Finally block implementation. __ bind(&finally_entry); @@ -1507,13 +1476,11 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { -#ifdef ENABLE_DEBUGGER_SUPPORT Comment cmnt(masm_, "[ DebuggerStatement"); SetStatementPosition(stmt); __ DebugBreak(); // Ignore the return value. -#endif } @@ -1590,8 +1557,10 @@ void FullCodeGenerator::VisitNativeFunctionLiteral( Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); bool is_generator = false; Handle<SharedFunctionInfo> shared = - isolate()->factory()->NewSharedFunctionInfo(name, literals, is_generator, - code, Handle<ScopeInfo>(fun->shared()->scope_info())); + isolate()->factory()->NewSharedFunctionInfo( + name, literals, is_generator, + code, Handle<ScopeInfo>(fun->shared()->scope_info()), + Handle<FixedArray>(fun->shared()->feedback_vector())); shared->set_construct_stub(*construct_stub); // Copy the function data to the shared function info. @@ -1606,7 +1575,7 @@ void FullCodeGenerator::VisitNativeFunctionLiteral( void FullCodeGenerator::VisitThrow(Throw* expr) { Comment cmnt(masm_, "[ Throw"); VisitForStackValue(expr->exception()); - __ CallRuntime(Runtime::kThrow, 1); + __ CallRuntime(Runtime::kHiddenThrow, 1); // Never returns here. } @@ -1644,8 +1613,7 @@ bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) { } -void BackEdgeTable::Patch(Isolate* isolate, - Code* unoptimized) { +void BackEdgeTable::Patch(Isolate* isolate, Code* unoptimized) { DisallowHeapAllocation no_gc; Code* patch = isolate->builtins()->builtin(Builtins::kOnStackReplacement); @@ -1668,8 +1636,7 @@ void BackEdgeTable::Patch(Isolate* isolate, } -void BackEdgeTable::Revert(Isolate* isolate, - Code* unoptimized) { +void BackEdgeTable::Revert(Isolate* isolate, Code* unoptimized) { DisallowHeapAllocation no_gc; Code* patch = isolate->builtins()->builtin(Builtins::kInterruptCheck); @@ -1694,25 +1661,23 @@ void BackEdgeTable::Revert(Isolate* isolate, } -void BackEdgeTable::AddStackCheck(CompilationInfo* info) { +void BackEdgeTable::AddStackCheck(Handle<Code> code, uint32_t pc_offset) { DisallowHeapAllocation no_gc; - Isolate* isolate = info->isolate(); - Code* code = info->shared_info()->code(); - Address pc = code->instruction_start() + info->osr_pc_offset(); - ASSERT_EQ(ON_STACK_REPLACEMENT, GetBackEdgeState(isolate, code, pc)); + Isolate* isolate = code->GetIsolate(); + Address pc = code->instruction_start() + pc_offset; Code* patch = isolate->builtins()->builtin(Builtins::kOsrAfterStackCheck); - PatchAt(code, pc, OSR_AFTER_STACK_CHECK, patch); + PatchAt(*code, pc, OSR_AFTER_STACK_CHECK, patch); } -void BackEdgeTable::RemoveStackCheck(CompilationInfo* info) { +void BackEdgeTable::RemoveStackCheck(Handle<Code> code, uint32_t pc_offset) { DisallowHeapAllocation no_gc; - Isolate* isolate = info->isolate(); - Code* code = info->shared_info()->code(); - Address pc = code->instruction_start() + info->osr_pc_offset(); - if (GetBackEdgeState(isolate, code, pc) == OSR_AFTER_STACK_CHECK) { + Isolate* isolate = code->GetIsolate(); + Address pc = code->instruction_start() + pc_offset; + + if (OSR_AFTER_STACK_CHECK == GetBackEdgeState(isolate, *code, pc)) { Code* patch = isolate->builtins()->builtin(Builtins::kOnStackReplacement); - PatchAt(code, pc, ON_STACK_REPLACEMENT, patch); + PatchAt(*code, pc, ON_STACK_REPLACEMENT, patch); } } |