summaryrefslogtreecommitdiffstats
path: root/chromium/v8/src/full-codegen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/full-codegen.cc')
-rw-r--r--chromium/v8/src/full-codegen.cc215
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);
}
}