Revert "Moved type feedback vector to SharedFunctionInfo."
This reverts commit 828f1d563a3f0972135886888fd26526e04da07f. Conflicts: src/compiler.cc test/cctest/test-compiler.cc BUG= R=titzer@chromium.org Review URL: https://codereview.chromium.org/196283015 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19911 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
e8939a5451
commit
7b810f4593
@ -129,6 +129,8 @@ void FullCodeGenerator::Generate() {
|
|||||||
handler_table_ =
|
handler_table_ =
|
||||||
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
|
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
|
||||||
|
|
||||||
|
InitializeFeedbackVector();
|
||||||
|
|
||||||
profiling_counter_ = isolate()->factory()->NewCell(
|
profiling_counter_ = isolate()->factory()->NewCell(
|
||||||
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
|
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
|
||||||
SetFunctionPosition(function());
|
SetFunctionPosition(function());
|
||||||
@ -1160,8 +1162,12 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
// We got a fixed array in register x0. Iterate through that.
|
// We got a fixed array in register x0. Iterate through that.
|
||||||
__ Bind(&fixed_array);
|
__ Bind(&fixed_array);
|
||||||
|
|
||||||
|
Handle<Object> feedback = Handle<Object>(
|
||||||
|
Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
|
||||||
|
isolate());
|
||||||
|
StoreFeedbackVectorSlot(slot, feedback);
|
||||||
__ LoadObject(x1, FeedbackVector());
|
__ LoadObject(x1, FeedbackVector());
|
||||||
__ Mov(x10, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
|
__ Mov(x10, Operand(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
|
||||||
__ Str(x10, FieldMemOperand(x1, FixedArray::OffsetOfElementAt(slot)));
|
__ Str(x10, FieldMemOperand(x1, FixedArray::OffsetOfElementAt(slot)));
|
||||||
|
|
||||||
__ Mov(x1, Operand(Smi::FromInt(1))); // Smi indicates slow check.
|
__ Mov(x1, Operand(Smi::FromInt(1))); // Smi indicates slow check.
|
||||||
@ -2408,6 +2414,9 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
|
|||||||
// Record source position for debugger.
|
// Record source position for debugger.
|
||||||
SetSourcePosition(expr->position());
|
SetSourcePosition(expr->position());
|
||||||
|
|
||||||
|
Handle<Object> uninitialized =
|
||||||
|
TypeFeedbackInfo::UninitializedSentinel(isolate());
|
||||||
|
StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
|
||||||
__ LoadObject(x2, FeedbackVector());
|
__ LoadObject(x2, FeedbackVector());
|
||||||
__ Mov(x3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
|
__ Mov(x3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
|
||||||
|
|
||||||
@ -2604,6 +2613,9 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
|||||||
__ Peek(x1, arg_count * kXRegSize);
|
__ Peek(x1, arg_count * kXRegSize);
|
||||||
|
|
||||||
// Record call targets in unoptimized code.
|
// Record call targets in unoptimized code.
|
||||||
|
Handle<Object> uninitialized =
|
||||||
|
TypeFeedbackInfo::UninitializedSentinel(isolate());
|
||||||
|
StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
|
||||||
__ LoadObject(x2, FeedbackVector());
|
__ LoadObject(x2, FeedbackVector());
|
||||||
__ Mov(x3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
|
__ Mov(x3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
|
||||||
|
|
||||||
|
@ -131,6 +131,8 @@ void FullCodeGenerator::Generate() {
|
|||||||
handler_table_ =
|
handler_table_ =
|
||||||
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
|
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
|
||||||
|
|
||||||
|
InitializeFeedbackVector();
|
||||||
|
|
||||||
profiling_counter_ = isolate()->factory()->NewCell(
|
profiling_counter_ = isolate()->factory()->NewCell(
|
||||||
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
|
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
|
||||||
SetFunctionPosition(function());
|
SetFunctionPosition(function());
|
||||||
@ -1164,8 +1166,12 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
Label non_proxy;
|
Label non_proxy;
|
||||||
__ bind(&fixed_array);
|
__ bind(&fixed_array);
|
||||||
|
|
||||||
|
Handle<Object> feedback = Handle<Object>(
|
||||||
|
Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
|
||||||
|
isolate());
|
||||||
|
StoreFeedbackVectorSlot(slot, feedback);
|
||||||
__ Move(r1, FeedbackVector());
|
__ Move(r1, FeedbackVector());
|
||||||
__ mov(r2, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
|
__ mov(r2, Operand(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
|
||||||
__ str(r2, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(slot)));
|
__ str(r2, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(slot)));
|
||||||
|
|
||||||
__ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check
|
__ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check
|
||||||
@ -2705,6 +2711,9 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
|
|||||||
// Record source position for debugger.
|
// Record source position for debugger.
|
||||||
SetSourcePosition(expr->position());
|
SetSourcePosition(expr->position());
|
||||||
|
|
||||||
|
Handle<Object> uninitialized =
|
||||||
|
TypeFeedbackInfo::UninitializedSentinel(isolate());
|
||||||
|
StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
|
||||||
__ Move(r2, FeedbackVector());
|
__ Move(r2, FeedbackVector());
|
||||||
__ mov(r3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
|
__ mov(r3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
|
||||||
|
|
||||||
@ -2891,6 +2900,9 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
|||||||
__ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
|
__ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
|
||||||
|
|
||||||
// Record call targets in unoptimized code.
|
// Record call targets in unoptimized code.
|
||||||
|
Handle<Object> uninitialized =
|
||||||
|
TypeFeedbackInfo::UninitializedSentinel(isolate());
|
||||||
|
StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
|
||||||
__ Move(r2, FeedbackVector());
|
__ Move(r2, FeedbackVector());
|
||||||
__ mov(r3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
|
__ mov(r3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
|
||||||
|
|
||||||
|
@ -140,13 +140,6 @@ void CompilationInfo::Initialize(Isolate* isolate,
|
|||||||
SetStrictMode(shared_info_->strict_mode());
|
SetStrictMode(shared_info_->strict_mode());
|
||||||
}
|
}
|
||||||
set_bailout_reason(kUnknown);
|
set_bailout_reason(kUnknown);
|
||||||
|
|
||||||
if (!shared_info().is_null() && shared_info()->is_compiled()) {
|
|
||||||
// We should initialize the CompilationInfo feedback vector from the
|
|
||||||
// passed in shared info, rather than creating a new one.
|
|
||||||
feedback_vector_ = Handle<FixedArray>(shared_info()->feedback_vector(),
|
|
||||||
isolate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -256,20 +249,6 @@ void CompilationInfo::PrepareForCompilation(Scope* scope) {
|
|||||||
ASSERT(scope_ == NULL);
|
ASSERT(scope_ == NULL);
|
||||||
scope_ = scope;
|
scope_ = scope;
|
||||||
function()->ProcessFeedbackSlots(isolate_);
|
function()->ProcessFeedbackSlots(isolate_);
|
||||||
int length = function()->slot_count();
|
|
||||||
if (feedback_vector_.is_null()) {
|
|
||||||
// Allocate the feedback vector too.
|
|
||||||
feedback_vector_ = isolate()->factory()->NewFixedArray(length, TENURED);
|
|
||||||
// Ensure we can skip the write barrier
|
|
||||||
ASSERT_EQ(isolate()->heap()->uninitialized_symbol(),
|
|
||||||
*TypeFeedbackInfo::UninitializedSentinel(isolate()));
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
feedback_vector_->set(i,
|
|
||||||
*TypeFeedbackInfo::UninitializedSentinel(isolate()),
|
|
||||||
SKIP_WRITE_BARRIER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ASSERT(feedback_vector_->length() == length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -591,8 +570,6 @@ static void UpdateSharedFunctionInfo(CompilationInfo* info) {
|
|||||||
shared->ReplaceCode(*code);
|
shared->ReplaceCode(*code);
|
||||||
if (shared->optimization_disabled()) code->set_optimizable(false);
|
if (shared->optimization_disabled()) code->set_optimizable(false);
|
||||||
|
|
||||||
shared->set_feedback_vector(*info->feedback_vector());
|
|
||||||
|
|
||||||
// Set the expected number of properties for instances.
|
// Set the expected number of properties for instances.
|
||||||
FunctionLiteral* lit = info->function();
|
FunctionLiteral* lit = info->function();
|
||||||
int expected = lit->expected_property_count();
|
int expected = lit->expected_property_count();
|
||||||
@ -846,8 +823,7 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
|
|||||||
lit->materialized_literal_count(),
|
lit->materialized_literal_count(),
|
||||||
lit->is_generator(),
|
lit->is_generator(),
|
||||||
info->code(),
|
info->code(),
|
||||||
ScopeInfo::Create(info->scope(), info->zone()),
|
ScopeInfo::Create(info->scope(), info->zone()));
|
||||||
info->feedback_vector());
|
|
||||||
|
|
||||||
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
|
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
|
||||||
SetFunctionInfo(result, lit, true, script);
|
SetFunctionInfo(result, lit, true, script);
|
||||||
@ -1046,8 +1022,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
|
|||||||
literal->materialized_literal_count(),
|
literal->materialized_literal_count(),
|
||||||
literal->is_generator(),
|
literal->is_generator(),
|
||||||
info.code(),
|
info.code(),
|
||||||
scope_info,
|
scope_info);
|
||||||
info.feedback_vector());
|
|
||||||
SetFunctionInfo(result, literal, false, script);
|
SetFunctionInfo(result, literal, false, script);
|
||||||
RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
|
RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
|
||||||
result->set_allows_lazy_compilation(allow_lazy);
|
result->set_allows_lazy_compilation(allow_lazy);
|
||||||
|
@ -175,9 +175,6 @@ class CompilationInfo {
|
|||||||
ASSERT(global_scope_ == NULL);
|
ASSERT(global_scope_ == NULL);
|
||||||
global_scope_ = global_scope;
|
global_scope_ = global_scope;
|
||||||
}
|
}
|
||||||
Handle<FixedArray> feedback_vector() const {
|
|
||||||
return feedback_vector_;
|
|
||||||
}
|
|
||||||
void SetCode(Handle<Code> code) { code_ = code; }
|
void SetCode(Handle<Code> code) { code_ = code; }
|
||||||
void SetExtension(v8::Extension* extension) {
|
void SetExtension(v8::Extension* extension) {
|
||||||
ASSERT(!is_lazy());
|
ASSERT(!is_lazy());
|
||||||
@ -406,9 +403,6 @@ class CompilationInfo {
|
|||||||
// global script. Will be a null handle otherwise.
|
// global script. Will be a null handle otherwise.
|
||||||
Handle<Context> context_;
|
Handle<Context> context_;
|
||||||
|
|
||||||
// Used by codegen, ultimately kept rooted by the SharedFunctionInfo.
|
|
||||||
Handle<FixedArray> feedback_vector_;
|
|
||||||
|
|
||||||
// Compilation mode flag and whether deoptimization is allowed.
|
// Compilation mode flag and whether deoptimization is allowed.
|
||||||
Mode mode_;
|
Mode mode_;
|
||||||
BailoutId osr_ast_id_;
|
BailoutId osr_ast_id_;
|
||||||
|
@ -1542,12 +1542,10 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
|
|||||||
int number_of_literals,
|
int number_of_literals,
|
||||||
bool is_generator,
|
bool is_generator,
|
||||||
Handle<Code> code,
|
Handle<Code> code,
|
||||||
Handle<ScopeInfo> scope_info,
|
Handle<ScopeInfo> scope_info) {
|
||||||
Handle<FixedArray> feedback_vector) {
|
|
||||||
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
|
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
|
||||||
shared->set_code(*code);
|
shared->set_code(*code);
|
||||||
shared->set_scope_info(*scope_info);
|
shared->set_scope_info(*scope_info);
|
||||||
shared->set_feedback_vector(*feedback_vector);
|
|
||||||
int literals_array_size = number_of_literals;
|
int literals_array_size = number_of_literals;
|
||||||
// If the function contains object, regexp or array literals,
|
// If the function contains object, regexp or array literals,
|
||||||
// allocate extra space for a literals array prefix containing the
|
// allocate extra space for a literals array prefix containing the
|
||||||
|
@ -517,8 +517,7 @@ class Factory {
|
|||||||
int number_of_literals,
|
int number_of_literals,
|
||||||
bool is_generator,
|
bool is_generator,
|
||||||
Handle<Code> code,
|
Handle<Code> code,
|
||||||
Handle<ScopeInfo> scope_info,
|
Handle<ScopeInfo> scope_info);
|
||||||
Handle<FixedArray> feedback_vector);
|
|
||||||
Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
|
Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
|
||||||
|
|
||||||
Handle<JSMessageObject> NewJSMessageObject(
|
Handle<JSMessageObject> NewJSMessageObject(
|
||||||
|
@ -386,6 +386,18 @@ unsigned FullCodeGenerator::EmitBackEdgeTable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FullCodeGenerator::InitializeFeedbackVector() {
|
||||||
|
int length = info_->function()->slot_count();
|
||||||
|
feedback_vector_ = isolate()->factory()->NewFixedArray(length, TENURED);
|
||||||
|
Handle<Object> sentinel = TypeFeedbackInfo::UninitializedSentinel(isolate());
|
||||||
|
// Ensure that it's safe to set without using a write barrier.
|
||||||
|
ASSERT_EQ(isolate()->heap()->uninitialized_symbol(), *sentinel);
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
feedback_vector_->set(i, *sentinel, SKIP_WRITE_BARRIER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
|
void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
|
||||||
// Fill in the deoptimization information.
|
// Fill in the deoptimization information.
|
||||||
ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
|
ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
|
||||||
@ -404,6 +416,7 @@ void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
|
|||||||
void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
|
void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
|
||||||
Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo();
|
Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo();
|
||||||
info->set_ic_total_count(ic_total_count_);
|
info->set_ic_total_count(ic_total_count_);
|
||||||
|
info->set_feedback_vector(*FeedbackVector());
|
||||||
ASSERT(!isolate()->heap()->InNewSpace(*info));
|
ASSERT(!isolate()->heap()->InNewSpace(*info));
|
||||||
code->set_type_feedback_info(*info);
|
code->set_type_feedback_info(*info);
|
||||||
}
|
}
|
||||||
@ -1605,8 +1618,7 @@ void FullCodeGenerator::VisitNativeFunctionLiteral(
|
|||||||
bool is_generator = false;
|
bool is_generator = false;
|
||||||
Handle<SharedFunctionInfo> shared =
|
Handle<SharedFunctionInfo> shared =
|
||||||
isolate()->factory()->NewSharedFunctionInfo(name, literals, is_generator,
|
isolate()->factory()->NewSharedFunctionInfo(name, literals, is_generator,
|
||||||
code, Handle<ScopeInfo>(fun->shared()->scope_info()),
|
code, Handle<ScopeInfo>(fun->shared()->scope_info()));
|
||||||
Handle<FixedArray>(fun->shared()->feedback_vector()));
|
|
||||||
shared->set_construct_stub(*construct_stub);
|
shared->set_construct_stub(*construct_stub);
|
||||||
|
|
||||||
// Copy the function data to the shared function info.
|
// Copy the function data to the shared function info.
|
||||||
|
@ -437,8 +437,12 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
// Feedback slot support. The feedback vector will be cleared during gc and
|
// Feedback slot support. The feedback vector will be cleared during gc and
|
||||||
// collected by the type-feedback oracle.
|
// collected by the type-feedback oracle.
|
||||||
Handle<FixedArray> FeedbackVector() {
|
Handle<FixedArray> FeedbackVector() {
|
||||||
return info_->feedback_vector();
|
return feedback_vector_;
|
||||||
}
|
}
|
||||||
|
void StoreFeedbackVectorSlot(int slot, Handle<Object> object) {
|
||||||
|
feedback_vector_->set(slot, *object);
|
||||||
|
}
|
||||||
|
void InitializeFeedbackVector();
|
||||||
|
|
||||||
// Record a call's return site offset, used to rebuild the frame if the
|
// Record a call's return site offset, used to rebuild the frame if the
|
||||||
// called function was inlined at the site.
|
// called function was inlined at the site.
|
||||||
@ -840,6 +844,7 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
ZoneList<BackEdgeEntry> back_edges_;
|
ZoneList<BackEdgeEntry> back_edges_;
|
||||||
int ic_total_count_;
|
int ic_total_count_;
|
||||||
Handle<FixedArray> handler_table_;
|
Handle<FixedArray> handler_table_;
|
||||||
|
Handle<FixedArray> feedback_vector_;
|
||||||
Handle<Cell> profiling_counter_;
|
Handle<Cell> profiling_counter_;
|
||||||
bool generate_debug_code_;
|
bool generate_debug_code_;
|
||||||
|
|
||||||
|
@ -1398,9 +1398,6 @@ void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
|
|||||||
SetInternalReference(obj, entry,
|
SetInternalReference(obj, entry,
|
||||||
"optimized_code_map", shared->optimized_code_map(),
|
"optimized_code_map", shared->optimized_code_map(),
|
||||||
SharedFunctionInfo::kOptimizedCodeMapOffset);
|
SharedFunctionInfo::kOptimizedCodeMapOffset);
|
||||||
SetInternalReference(obj, entry,
|
|
||||||
"feedback_vector", shared->feedback_vector(),
|
|
||||||
SharedFunctionInfo::kFeedbackVectorOffset);
|
|
||||||
SetWeakReference(obj, entry,
|
SetWeakReference(obj, entry,
|
||||||
"initial_map", shared->initial_map(),
|
"initial_map", shared->initial_map(),
|
||||||
SharedFunctionInfo::kInitialMapOffset);
|
SharedFunctionInfo::kInitialMapOffset);
|
||||||
|
@ -2687,6 +2687,7 @@ MaybeObject* Heap::AllocateTypeFeedbackInfo() {
|
|||||||
if (!maybe_info->To(&info)) return maybe_info;
|
if (!maybe_info->To(&info)) return maybe_info;
|
||||||
}
|
}
|
||||||
info->initialize_storage();
|
info->initialize_storage();
|
||||||
|
info->set_feedback_vector(empty_fixed_array(), SKIP_WRITE_BARRIER);
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3808,7 +3809,6 @@ MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) {
|
|||||||
share->set_script(undefined_value(), SKIP_WRITE_BARRIER);
|
share->set_script(undefined_value(), SKIP_WRITE_BARRIER);
|
||||||
share->set_debug_info(undefined_value(), SKIP_WRITE_BARRIER);
|
share->set_debug_info(undefined_value(), SKIP_WRITE_BARRIER);
|
||||||
share->set_inferred_name(empty_string(), SKIP_WRITE_BARRIER);
|
share->set_inferred_name(empty_string(), SKIP_WRITE_BARRIER);
|
||||||
share->set_feedback_vector(empty_fixed_array(), SKIP_WRITE_BARRIER);
|
|
||||||
share->set_initial_map(undefined_value(), SKIP_WRITE_BARRIER);
|
share->set_initial_map(undefined_value(), SKIP_WRITE_BARRIER);
|
||||||
share->set_ast_node_count(0);
|
share->set_ast_node_count(0);
|
||||||
share->set_counters(0);
|
share->set_counters(0);
|
||||||
|
@ -7206,7 +7206,6 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
|
|||||||
target_shared->set_scope_info(*target_scope_info);
|
target_shared->set_scope_info(*target_scope_info);
|
||||||
}
|
}
|
||||||
target_shared->EnableDeoptimizationSupport(*target_info.code());
|
target_shared->EnableDeoptimizationSupport(*target_info.code());
|
||||||
target_shared->set_feedback_vector(*target_info.feedback_vector());
|
|
||||||
Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
|
Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
|
||||||
&target_info,
|
&target_info,
|
||||||
target_shared);
|
target_shared);
|
||||||
|
@ -119,6 +119,8 @@ void FullCodeGenerator::Generate() {
|
|||||||
handler_table_ =
|
handler_table_ =
|
||||||
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
|
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
|
||||||
|
|
||||||
|
InitializeFeedbackVector();
|
||||||
|
|
||||||
profiling_counter_ = isolate()->factory()->NewCell(
|
profiling_counter_ = isolate()->factory()->NewCell(
|
||||||
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
|
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
|
||||||
SetFunctionPosition(function());
|
SetFunctionPosition(function());
|
||||||
@ -1102,10 +1104,15 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
Label non_proxy;
|
Label non_proxy;
|
||||||
__ bind(&fixed_array);
|
__ bind(&fixed_array);
|
||||||
|
|
||||||
|
Handle<Object> feedback = Handle<Object>(
|
||||||
|
Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
|
||||||
|
isolate());
|
||||||
|
StoreFeedbackVectorSlot(slot, feedback);
|
||||||
|
|
||||||
// No need for a write barrier, we are storing a Smi in the feedback vector.
|
// No need for a write barrier, we are storing a Smi in the feedback vector.
|
||||||
__ LoadHeapObject(ebx, FeedbackVector());
|
__ LoadHeapObject(ebx, FeedbackVector());
|
||||||
__ mov(FieldOperand(ebx, FixedArray::OffsetOfElementAt(slot)),
|
__ mov(FieldOperand(ebx, FixedArray::OffsetOfElementAt(slot)),
|
||||||
Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
|
Immediate(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
|
||||||
|
|
||||||
__ mov(ebx, Immediate(Smi::FromInt(1))); // Smi indicates slow check
|
__ mov(ebx, Immediate(Smi::FromInt(1))); // Smi indicates slow check
|
||||||
__ mov(ecx, Operand(esp, 0 * kPointerSize)); // Get enumerated object
|
__ mov(ecx, Operand(esp, 0 * kPointerSize)); // Get enumerated object
|
||||||
@ -2658,6 +2665,9 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
|
|||||||
// Record source position for debugger.
|
// Record source position for debugger.
|
||||||
SetSourcePosition(expr->position());
|
SetSourcePosition(expr->position());
|
||||||
|
|
||||||
|
Handle<Object> uninitialized =
|
||||||
|
TypeFeedbackInfo::UninitializedSentinel(isolate());
|
||||||
|
StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
|
||||||
__ LoadHeapObject(ebx, FeedbackVector());
|
__ LoadHeapObject(ebx, FeedbackVector());
|
||||||
__ mov(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot())));
|
__ mov(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot())));
|
||||||
|
|
||||||
@ -2835,6 +2845,9 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
|||||||
__ mov(edi, Operand(esp, arg_count * kPointerSize));
|
__ mov(edi, Operand(esp, arg_count * kPointerSize));
|
||||||
|
|
||||||
// Record call targets in unoptimized code.
|
// Record call targets in unoptimized code.
|
||||||
|
Handle<Object> uninitialized =
|
||||||
|
TypeFeedbackInfo::UninitializedSentinel(isolate());
|
||||||
|
StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
|
||||||
__ LoadHeapObject(ebx, FeedbackVector());
|
__ LoadHeapObject(ebx, FeedbackVector());
|
||||||
__ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot())));
|
__ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot())));
|
||||||
|
|
||||||
|
@ -139,6 +139,8 @@ void FullCodeGenerator::Generate() {
|
|||||||
handler_table_ =
|
handler_table_ =
|
||||||
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
|
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
|
||||||
|
|
||||||
|
InitializeFeedbackVector();
|
||||||
|
|
||||||
profiling_counter_ = isolate()->factory()->NewCell(
|
profiling_counter_ = isolate()->factory()->NewCell(
|
||||||
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
|
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
|
||||||
SetFunctionPosition(function());
|
SetFunctionPosition(function());
|
||||||
@ -1174,8 +1176,12 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
Label non_proxy;
|
Label non_proxy;
|
||||||
__ bind(&fixed_array);
|
__ bind(&fixed_array);
|
||||||
|
|
||||||
|
Handle<Object> feedback = Handle<Object>(
|
||||||
|
Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
|
||||||
|
isolate());
|
||||||
|
StoreFeedbackVectorSlot(slot, feedback);
|
||||||
__ li(a1, FeedbackVector());
|
__ li(a1, FeedbackVector());
|
||||||
__ li(a2, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
|
__ li(a2, Operand(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
|
||||||
__ sw(a2, FieldMemOperand(a1, FixedArray::OffsetOfElementAt(slot)));
|
__ sw(a2, FieldMemOperand(a1, FixedArray::OffsetOfElementAt(slot)));
|
||||||
|
|
||||||
__ li(a1, Operand(Smi::FromInt(1))); // Smi indicates slow check
|
__ li(a1, Operand(Smi::FromInt(1))); // Smi indicates slow check
|
||||||
@ -2729,6 +2735,9 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
|
|||||||
// Record source position for debugger.
|
// Record source position for debugger.
|
||||||
SetSourcePosition(expr->position());
|
SetSourcePosition(expr->position());
|
||||||
|
|
||||||
|
Handle<Object> uninitialized =
|
||||||
|
TypeFeedbackInfo::UninitializedSentinel(isolate());
|
||||||
|
StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
|
||||||
__ li(a2, FeedbackVector());
|
__ li(a2, FeedbackVector());
|
||||||
__ li(a3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
|
__ li(a3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
|
||||||
|
|
||||||
@ -2913,6 +2922,9 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
|||||||
__ lw(a1, MemOperand(sp, arg_count * kPointerSize));
|
__ lw(a1, MemOperand(sp, arg_count * kPointerSize));
|
||||||
|
|
||||||
// Record call targets in unoptimized code.
|
// Record call targets in unoptimized code.
|
||||||
|
Handle<Object> uninitialized =
|
||||||
|
TypeFeedbackInfo::UninitializedSentinel(isolate());
|
||||||
|
StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
|
||||||
__ li(a2, FeedbackVector());
|
__ li(a2, FeedbackVector());
|
||||||
__ li(a3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
|
__ li(a3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
|
||||||
|
|
||||||
|
@ -368,6 +368,7 @@ void PolymorphicCodeCache::PolymorphicCodeCacheVerify() {
|
|||||||
void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
|
void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
|
||||||
VerifyObjectField(kStorage1Offset);
|
VerifyObjectField(kStorage1Offset);
|
||||||
VerifyObjectField(kStorage2Offset);
|
VerifyObjectField(kStorage2Offset);
|
||||||
|
VerifyHeapPointer(feedback_vector());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -551,7 +552,6 @@ void SharedFunctionInfo::SharedFunctionInfoVerify() {
|
|||||||
VerifyObjectField(kNameOffset);
|
VerifyObjectField(kNameOffset);
|
||||||
VerifyObjectField(kCodeOffset);
|
VerifyObjectField(kCodeOffset);
|
||||||
VerifyObjectField(kOptimizedCodeMapOffset);
|
VerifyObjectField(kOptimizedCodeMapOffset);
|
||||||
VerifyObjectField(kFeedbackVectorOffset);
|
|
||||||
VerifyObjectField(kScopeInfoOffset);
|
VerifyObjectField(kScopeInfoOffset);
|
||||||
VerifyObjectField(kInstanceClassNameOffset);
|
VerifyObjectField(kInstanceClassNameOffset);
|
||||||
VerifyObjectField(kFunctionDataOffset);
|
VerifyObjectField(kFunctionDataOffset);
|
||||||
|
@ -1481,7 +1481,7 @@ AllocationSiteMode AllocationSite::GetMode(
|
|||||||
AllocationSiteMode AllocationSite::GetMode(ElementsKind from,
|
AllocationSiteMode AllocationSite::GetMode(ElementsKind from,
|
||||||
ElementsKind to) {
|
ElementsKind to) {
|
||||||
if (IsFastSmiElementsKind(from) &&
|
if (IsFastSmiElementsKind(from) &&
|
||||||
IsMoreGeneralElementsKindTransition(from, to)) {
|
IsMoreGeneralElementsKindTransition(from, to)) {
|
||||||
return TRACK_ALLOCATION_SITE;
|
return TRACK_ALLOCATION_SITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4980,8 +4980,6 @@ ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
|
|||||||
ACCESSORS(SharedFunctionInfo, optimized_code_map, Object,
|
ACCESSORS(SharedFunctionInfo, optimized_code_map, Object,
|
||||||
kOptimizedCodeMapOffset)
|
kOptimizedCodeMapOffset)
|
||||||
ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
|
ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
|
||||||
ACCESSORS(SharedFunctionInfo, feedback_vector, FixedArray,
|
|
||||||
kFeedbackVectorOffset)
|
|
||||||
ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
|
ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
|
||||||
ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
|
ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
|
||||||
kInstanceClassNameOffset)
|
kInstanceClassNameOffset)
|
||||||
@ -6654,6 +6652,10 @@ bool TypeFeedbackInfo::matches_inlined_type_change_checksum(int checksum) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ACCESSORS(TypeFeedbackInfo, feedback_vector, FixedArray,
|
||||||
|
kFeedbackVectorOffset)
|
||||||
|
|
||||||
|
|
||||||
SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)
|
SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)
|
||||||
|
|
||||||
|
|
||||||
|
@ -566,6 +566,8 @@ void TypeFeedbackInfo::TypeFeedbackInfoPrint(FILE* out) {
|
|||||||
HeapObject::PrintHeader(out, "TypeFeedbackInfo");
|
HeapObject::PrintHeader(out, "TypeFeedbackInfo");
|
||||||
PrintF(out, " - ic_total_count: %d, ic_with_type_info_count: %d\n",
|
PrintF(out, " - ic_total_count: %d, ic_with_type_info_count: %d\n",
|
||||||
ic_total_count(), ic_with_type_info_count());
|
ic_total_count(), ic_with_type_info_count());
|
||||||
|
PrintF(out, " - feedback_vector: ");
|
||||||
|
feedback_vector()->FixedArrayPrint(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -879,8 +881,6 @@ void SharedFunctionInfo::SharedFunctionInfoPrint(FILE* out) {
|
|||||||
PrintF(out, "\n - length = %d", length());
|
PrintF(out, "\n - length = %d", length());
|
||||||
PrintF(out, "\n - optimized_code_map = ");
|
PrintF(out, "\n - optimized_code_map = ");
|
||||||
optimized_code_map()->ShortPrint(out);
|
optimized_code_map()->ShortPrint(out);
|
||||||
PrintF(out, "\n - feedback_vector = ");
|
|
||||||
feedback_vector()->FixedArrayPrint(out);
|
|
||||||
PrintF(out, "\n");
|
PrintF(out, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,6 +427,9 @@ void StaticMarkingVisitor<StaticVisitor>::VisitCode(
|
|||||||
Map* map, HeapObject* object) {
|
Map* map, HeapObject* object) {
|
||||||
Heap* heap = map->GetHeap();
|
Heap* heap = map->GetHeap();
|
||||||
Code* code = Code::cast(object);
|
Code* code = Code::cast(object);
|
||||||
|
if (FLAG_cleanup_code_caches_at_gc) {
|
||||||
|
code->ClearTypeFeedbackInfo(heap);
|
||||||
|
}
|
||||||
if (FLAG_age_code && !Serializer::enabled()) {
|
if (FLAG_age_code && !Serializer::enabled()) {
|
||||||
code->MakeOlder(heap->mark_compact_collector()->marking_parity());
|
code->MakeOlder(heap->mark_compact_collector()->marking_parity());
|
||||||
}
|
}
|
||||||
@ -442,9 +445,6 @@ void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfo(
|
|||||||
if (shared->ic_age() != heap->global_ic_age()) {
|
if (shared->ic_age() != heap->global_ic_age()) {
|
||||||
shared->ResetForNewContext(heap->global_ic_age());
|
shared->ResetForNewContext(heap->global_ic_age());
|
||||||
}
|
}
|
||||||
if (FLAG_cleanup_code_caches_at_gc) {
|
|
||||||
shared->ClearTypeFeedbackInfo(heap);
|
|
||||||
}
|
|
||||||
if (FLAG_cache_optimized_code &&
|
if (FLAG_cache_optimized_code &&
|
||||||
FLAG_flush_optimized_code_cache &&
|
FLAG_flush_optimized_code_cache &&
|
||||||
!shared->optimized_code_map()->IsSmi()) {
|
!shared->optimized_code_map()->IsSmi()) {
|
||||||
|
@ -10640,16 +10640,19 @@ void Code::ClearInlineCaches(Code::Kind* kind) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SharedFunctionInfo::ClearTypeFeedbackInfo(Heap* heap) {
|
void Code::ClearTypeFeedbackInfo(Heap* heap) {
|
||||||
FixedArray* vector = feedback_vector();
|
if (kind() != FUNCTION) return;
|
||||||
for (int i = 0; i < vector->length(); i++) {
|
Object* raw_info = type_feedback_info();
|
||||||
Object* obj = vector->get(i);
|
if (raw_info->IsTypeFeedbackInfo()) {
|
||||||
if (!obj->IsAllocationSite()) {
|
FixedArray* feedback_vector =
|
||||||
// The assert verifies we can skip the write barrier.
|
TypeFeedbackInfo::cast(raw_info)->feedback_vector();
|
||||||
ASSERT(heap->uninitialized_symbol() ==
|
for (int i = 0; i < feedback_vector->length(); i++) {
|
||||||
TypeFeedbackInfo::RawUninitializedSentinel(heap));
|
Object* obj = feedback_vector->get(i);
|
||||||
vector->set(i, TypeFeedbackInfo::RawUninitializedSentinel(heap),
|
if (!obj->IsAllocationSite()) {
|
||||||
SKIP_WRITE_BARRIER);
|
// TODO(mvstanton): Can't I avoid a write barrier for this sentinel?
|
||||||
|
feedback_vector->set(i,
|
||||||
|
TypeFeedbackInfo::RawUninitializedSentinel(heap));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5497,6 +5497,8 @@ class Code: public HeapObject {
|
|||||||
void ClearInlineCaches();
|
void ClearInlineCaches();
|
||||||
void ClearInlineCaches(Kind kind);
|
void ClearInlineCaches(Kind kind);
|
||||||
|
|
||||||
|
void ClearTypeFeedbackInfo(Heap* heap);
|
||||||
|
|
||||||
BailoutId TranslatePcOffsetToAstId(uint32_t pc_offset);
|
BailoutId TranslatePcOffsetToAstId(uint32_t pc_offset);
|
||||||
uint32_t TranslateAstIdToPcOffset(BailoutId ast_id);
|
uint32_t TranslateAstIdToPcOffset(BailoutId ast_id);
|
||||||
|
|
||||||
@ -6692,8 +6694,6 @@ class SharedFunctionInfo: public HeapObject {
|
|||||||
// Removed a specific optimized code object from the optimized code map.
|
// Removed a specific optimized code object from the optimized code map.
|
||||||
void EvictFromOptimizedCodeMap(Code* optimized_code, const char* reason);
|
void EvictFromOptimizedCodeMap(Code* optimized_code, const char* reason);
|
||||||
|
|
||||||
void ClearTypeFeedbackInfo(Heap* heap);
|
|
||||||
|
|
||||||
// Trims the optimized code map after entries have been removed.
|
// Trims the optimized code map after entries have been removed.
|
||||||
void TrimOptimizedCodeMap(int shrink_by);
|
void TrimOptimizedCodeMap(int shrink_by);
|
||||||
|
|
||||||
@ -6802,12 +6802,6 @@ class SharedFunctionInfo: public HeapObject {
|
|||||||
inline int construction_count();
|
inline int construction_count();
|
||||||
inline void set_construction_count(int value);
|
inline void set_construction_count(int value);
|
||||||
|
|
||||||
// [feedback_vector] - accumulates ast node feedback from full-codegen and
|
|
||||||
// (increasingly) from crankshafted code where sufficient feedback isn't
|
|
||||||
// available. Currently the field is duplicated in
|
|
||||||
// TypeFeedbackInfo::feedback_vector, but the allocation is done here.
|
|
||||||
DECL_ACCESSORS(feedback_vector, FixedArray)
|
|
||||||
|
|
||||||
// [initial_map]: initial map of the first function called as a constructor.
|
// [initial_map]: initial map of the first function called as a constructor.
|
||||||
// Saved for the duration of the tracking phase.
|
// Saved for the duration of the tracking phase.
|
||||||
// This is a weak link (GC resets it to undefined_value if no other live
|
// This is a weak link (GC resets it to undefined_value if no other live
|
||||||
@ -7088,10 +7082,8 @@ class SharedFunctionInfo: public HeapObject {
|
|||||||
static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
|
static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
|
||||||
static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
|
static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
|
||||||
static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
|
static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
|
||||||
static const int kFeedbackVectorOffset =
|
|
||||||
kInferredNameOffset + kPointerSize;
|
|
||||||
static const int kInitialMapOffset =
|
static const int kInitialMapOffset =
|
||||||
kFeedbackVectorOffset + kPointerSize;
|
kInferredNameOffset + kPointerSize;
|
||||||
// ast_node_count is a Smi field. It could be grouped with another Smi field
|
// ast_node_count is a Smi field. It could be grouped with another Smi field
|
||||||
// into a PSEUDO_SMI_ACCESSORS pair (on x64), if one becomes available.
|
// into a PSEUDO_SMI_ACCESSORS pair (on x64), if one becomes available.
|
||||||
static const int kAstNodeCountOffset =
|
static const int kAstNodeCountOffset =
|
||||||
@ -8177,6 +8169,8 @@ class TypeFeedbackInfo: public Struct {
|
|||||||
inline void set_inlined_type_change_checksum(int checksum);
|
inline void set_inlined_type_change_checksum(int checksum);
|
||||||
inline bool matches_inlined_type_change_checksum(int checksum);
|
inline bool matches_inlined_type_change_checksum(int checksum);
|
||||||
|
|
||||||
|
DECL_ACCESSORS(feedback_vector, FixedArray)
|
||||||
|
|
||||||
static inline TypeFeedbackInfo* cast(Object* obj);
|
static inline TypeFeedbackInfo* cast(Object* obj);
|
||||||
|
|
||||||
// Dispatched behavior.
|
// Dispatched behavior.
|
||||||
@ -8185,9 +8179,10 @@ class TypeFeedbackInfo: public Struct {
|
|||||||
|
|
||||||
static const int kStorage1Offset = HeapObject::kHeaderSize;
|
static const int kStorage1Offset = HeapObject::kHeaderSize;
|
||||||
static const int kStorage2Offset = kStorage1Offset + kPointerSize;
|
static const int kStorage2Offset = kStorage1Offset + kPointerSize;
|
||||||
static const int kSize = kStorage2Offset + kPointerSize;
|
static const int kFeedbackVectorOffset =
|
||||||
|
kStorage2Offset + kPointerSize;
|
||||||
|
static const int kSize = kFeedbackVectorOffset + kPointerSize;
|
||||||
|
|
||||||
// TODO(mvstanton): move these sentinel declarations to shared function info.
|
|
||||||
// The object that indicates an uninitialized cache.
|
// The object that indicates an uninitialized cache.
|
||||||
static inline Handle<Object> UninitializedSentinel(Isolate* isolate);
|
static inline Handle<Object> UninitializedSentinel(Isolate* isolate);
|
||||||
|
|
||||||
@ -8203,6 +8198,9 @@ class TypeFeedbackInfo: public Struct {
|
|||||||
// garbage collection (e.g., for patching the cache).
|
// garbage collection (e.g., for patching the cache).
|
||||||
static inline Object* RawUninitializedSentinel(Heap* heap);
|
static inline Object* RawUninitializedSentinel(Heap* heap);
|
||||||
|
|
||||||
|
static const int kForInFastCaseMarker = 0;
|
||||||
|
static const int kForInSlowCaseMarker = 1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const int kTypeChangeChecksumBits = 7;
|
static const int kTypeChangeChecksumBits = 7;
|
||||||
|
|
||||||
|
@ -2929,7 +2929,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
|
|||||||
// Set the code, scope info, formal parameter count, and the length
|
// Set the code, scope info, formal parameter count, and the length
|
||||||
// of the target shared function info.
|
// of the target shared function info.
|
||||||
target_shared->ReplaceCode(source_shared->code());
|
target_shared->ReplaceCode(source_shared->code());
|
||||||
target_shared->set_feedback_vector(source_shared->feedback_vector());
|
|
||||||
target_shared->set_scope_info(source_shared->scope_info());
|
target_shared->set_scope_info(source_shared->scope_info());
|
||||||
target_shared->set_length(source_shared->length());
|
target_shared->set_length(source_shared->length());
|
||||||
target_shared->set_formal_parameter_count(
|
target_shared->set_formal_parameter_count(
|
||||||
@ -8478,10 +8477,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
|
|||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
ASSERT(args.length() == 1);
|
ASSERT(args.length() == 1);
|
||||||
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
|
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
|
||||||
function->shared()->ClearTypeFeedbackInfo(isolate->heap());
|
|
||||||
Code* unoptimized = function->shared()->code();
|
Code* unoptimized = function->shared()->code();
|
||||||
if (unoptimized->kind() == Code::FUNCTION) {
|
if (unoptimized->kind() == Code::FUNCTION) {
|
||||||
unoptimized->ClearInlineCaches();
|
unoptimized->ClearInlineCaches();
|
||||||
|
unoptimized->ClearTypeFeedbackInfo(isolate->heap());
|
||||||
}
|
}
|
||||||
return isolate->heap()->undefined_value();
|
return isolate->heap()->undefined_value();
|
||||||
}
|
}
|
||||||
|
@ -43,12 +43,16 @@ namespace internal {
|
|||||||
|
|
||||||
|
|
||||||
TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
|
TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
|
||||||
Handle<FixedArray> feedback_vector,
|
|
||||||
Handle<Context> native_context,
|
Handle<Context> native_context,
|
||||||
Zone* zone)
|
Zone* zone)
|
||||||
: native_context_(native_context),
|
: native_context_(native_context),
|
||||||
zone_(zone),
|
zone_(zone) {
|
||||||
feedback_vector_(feedback_vector) {
|
Object* raw_info = code->type_feedback_info();
|
||||||
|
if (raw_info->IsTypeFeedbackInfo()) {
|
||||||
|
feedback_vector_ = Handle<FixedArray>(TypeFeedbackInfo::cast(raw_info)->
|
||||||
|
feedback_vector());
|
||||||
|
}
|
||||||
|
|
||||||
BuildDictionary(code);
|
BuildDictionary(code);
|
||||||
ASSERT(dictionary_->IsDictionary());
|
ASSERT(dictionary_->IsDictionary());
|
||||||
}
|
}
|
||||||
@ -128,9 +132,9 @@ bool TypeFeedbackOracle::CallNewIsMonomorphic(int slot) {
|
|||||||
|
|
||||||
byte TypeFeedbackOracle::ForInType(int feedback_vector_slot) {
|
byte TypeFeedbackOracle::ForInType(int feedback_vector_slot) {
|
||||||
Handle<Object> value = GetInfo(feedback_vector_slot);
|
Handle<Object> value = GetInfo(feedback_vector_slot);
|
||||||
return value.is_identical_to(
|
return value->IsSmi() &&
|
||||||
TypeFeedbackInfo::UninitializedSentinel(isolate()))
|
Smi::cast(*value)->value() == TypeFeedbackInfo::kForInFastCaseMarker
|
||||||
? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN;
|
? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,7 +44,6 @@ class SmallMapList;
|
|||||||
class TypeFeedbackOracle: public ZoneObject {
|
class TypeFeedbackOracle: public ZoneObject {
|
||||||
public:
|
public:
|
||||||
TypeFeedbackOracle(Handle<Code> code,
|
TypeFeedbackOracle(Handle<Code> code,
|
||||||
Handle<FixedArray> feedback_vector,
|
|
||||||
Handle<Context> native_context,
|
Handle<Context> native_context,
|
||||||
Zone* zone);
|
Zone* zone);
|
||||||
|
|
||||||
|
@ -40,7 +40,6 @@ AstTyper::AstTyper(CompilationInfo* info)
|
|||||||
: info_(info),
|
: info_(info),
|
||||||
oracle_(
|
oracle_(
|
||||||
Handle<Code>(info->closure()->shared()->code()),
|
Handle<Code>(info->closure()->shared()->code()),
|
||||||
Handle<FixedArray>(info->closure()->shared()->feedback_vector()),
|
|
||||||
Handle<Context>(info->closure()->context()->native_context()),
|
Handle<Context>(info->closure()->context()->native_context()),
|
||||||
info->zone()),
|
info->zone()),
|
||||||
store_(info->zone()) {
|
store_(info->zone()) {
|
||||||
|
@ -119,6 +119,8 @@ void FullCodeGenerator::Generate() {
|
|||||||
handler_table_ =
|
handler_table_ =
|
||||||
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
|
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
|
||||||
|
|
||||||
|
InitializeFeedbackVector();
|
||||||
|
|
||||||
profiling_counter_ = isolate()->factory()->NewCell(
|
profiling_counter_ = isolate()->factory()->NewCell(
|
||||||
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
|
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
|
||||||
SetFunctionPosition(function());
|
SetFunctionPosition(function());
|
||||||
@ -1125,10 +1127,15 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
Label non_proxy;
|
Label non_proxy;
|
||||||
__ bind(&fixed_array);
|
__ bind(&fixed_array);
|
||||||
|
|
||||||
|
Handle<Object> feedback = Handle<Object>(
|
||||||
|
Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
|
||||||
|
isolate());
|
||||||
|
StoreFeedbackVectorSlot(slot, feedback);
|
||||||
|
|
||||||
// No need for a write barrier, we are storing a Smi in the feedback vector.
|
// No need for a write barrier, we are storing a Smi in the feedback vector.
|
||||||
__ Move(rbx, FeedbackVector());
|
__ Move(rbx, FeedbackVector());
|
||||||
__ Move(FieldOperand(rbx, FixedArray::OffsetOfElementAt(slot)),
|
__ Move(FieldOperand(rbx, FixedArray::OffsetOfElementAt(slot)),
|
||||||
TypeFeedbackInfo::MegamorphicSentinel(isolate()));
|
Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker));
|
||||||
__ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check
|
__ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check
|
||||||
__ movp(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object
|
__ movp(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object
|
||||||
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
|
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
|
||||||
@ -2641,6 +2648,9 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
|
|||||||
// Record source position for debugger.
|
// Record source position for debugger.
|
||||||
SetSourcePosition(expr->position());
|
SetSourcePosition(expr->position());
|
||||||
|
|
||||||
|
Handle<Object> uninitialized =
|
||||||
|
TypeFeedbackInfo::UninitializedSentinel(isolate());
|
||||||
|
StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
|
||||||
__ Move(rbx, FeedbackVector());
|
__ Move(rbx, FeedbackVector());
|
||||||
__ Move(rdx, Smi::FromInt(expr->CallFeedbackSlot()));
|
__ Move(rdx, Smi::FromInt(expr->CallFeedbackSlot()));
|
||||||
|
|
||||||
@ -2818,6 +2828,9 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
|||||||
__ movp(rdi, Operand(rsp, arg_count * kPointerSize));
|
__ movp(rdi, Operand(rsp, arg_count * kPointerSize));
|
||||||
|
|
||||||
// Record call targets in unoptimized code, but not in the snapshot.
|
// Record call targets in unoptimized code, but not in the snapshot.
|
||||||
|
Handle<Object> uninitialized =
|
||||||
|
TypeFeedbackInfo::UninitializedSentinel(isolate());
|
||||||
|
StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
|
||||||
__ Move(rbx, FeedbackVector());
|
__ Move(rbx, FeedbackVector());
|
||||||
__ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot()));
|
__ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot()));
|
||||||
|
|
||||||
|
@ -312,78 +312,6 @@ TEST(GetScriptLineNumber) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(FeedbackVectorPreservedAcrossRecompiles) {
|
|
||||||
if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
|
|
||||||
i::FLAG_allow_natives_syntax = true;
|
|
||||||
CcTest::InitializeVM();
|
|
||||||
if (!CcTest::i_isolate()->use_crankshaft()) return;
|
|
||||||
v8::HandleScope scope(CcTest::isolate());
|
|
||||||
|
|
||||||
// Make sure function f has a call that uses a type feedback slot.
|
|
||||||
CompileRun("function fun() {};"
|
|
||||||
"fun1 = fun;"
|
|
||||||
"function f(a) { a(); } f(fun1);");
|
|
||||||
|
|
||||||
Handle<JSFunction> f =
|
|
||||||
v8::Utils::OpenHandle(
|
|
||||||
*v8::Handle<v8::Function>::Cast(
|
|
||||||
CcTest::global()->Get(v8_str("f"))));
|
|
||||||
|
|
||||||
// We shouldn't have deoptimization support. We want to recompile and
|
|
||||||
// verify that our feedback vector preserves information.
|
|
||||||
CHECK(!f->shared()->has_deoptimization_support());
|
|
||||||
Handle<FixedArray> feedback_vector(f->shared()->feedback_vector());
|
|
||||||
|
|
||||||
// Verify that we gathered feedback.
|
|
||||||
CHECK_EQ(1, feedback_vector->length());
|
|
||||||
CHECK(feedback_vector->get(0)->IsJSFunction());
|
|
||||||
|
|
||||||
CompileRun("%OptimizeFunctionOnNextCall(f); f(fun1);");
|
|
||||||
|
|
||||||
// Verify that the feedback is still "gathered" despite a recompilation
|
|
||||||
// of the full code.
|
|
||||||
CHECK(f->shared()->has_deoptimization_support());
|
|
||||||
CHECK(f->shared()->feedback_vector()->get(0)->IsJSFunction());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST(FeedbackVectorRecreatedOnScopeChanges) {
|
|
||||||
if (i::FLAG_always_opt || !i::FLAG_lazy) return;
|
|
||||||
CcTest::InitializeVM();
|
|
||||||
v8::HandleScope scope(CcTest::isolate());
|
|
||||||
|
|
||||||
CompileRun("function builder() {"
|
|
||||||
" call_target = function() { return 3; };"
|
|
||||||
" return (function() {"
|
|
||||||
" eval('');"
|
|
||||||
" return function() {"
|
|
||||||
" 'use strict';"
|
|
||||||
" call_target();"
|
|
||||||
" }"
|
|
||||||
" })();"
|
|
||||||
"}"
|
|
||||||
"morphing_call = builder();");
|
|
||||||
|
|
||||||
Handle<JSFunction> f =
|
|
||||||
v8::Utils::OpenHandle(
|
|
||||||
*v8::Handle<v8::Function>::Cast(
|
|
||||||
CcTest::global()->Get(v8_str("morphing_call"))));
|
|
||||||
|
|
||||||
// morphing_call should have one feedback vector slot for the call to
|
|
||||||
// call_target(), scoping analysis having been performed.
|
|
||||||
CHECK_EQ(1, f->shared()->feedback_vector()->length());
|
|
||||||
// And yet it's not compiled.
|
|
||||||
CHECK(!f->shared()->is_compiled());
|
|
||||||
|
|
||||||
CompileRun("morphing_call();");
|
|
||||||
|
|
||||||
// On scoping analysis after lazy compile, the call is now a global
|
|
||||||
// call which needs no feedback vector slot.
|
|
||||||
CHECK_EQ(0, f->shared()->feedback_vector()->length());
|
|
||||||
CHECK(f->shared()->is_compiled());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Test that optimized code for different closures is actually shared
|
// Test that optimized code for different closures is actually shared
|
||||||
// immediately by the FastNewClosureStub when run in the same context.
|
// immediately by the FastNewClosureStub when run in the same context.
|
||||||
TEST(OptimizedCodeSharing) {
|
TEST(OptimizedCodeSharing) {
|
||||||
|
@ -2857,7 +2857,8 @@ TEST(IncrementalMarkingClearsTypeFeedbackInfo) {
|
|||||||
*v8::Handle<v8::Function>::Cast(
|
*v8::Handle<v8::Function>::Cast(
|
||||||
CcTest::global()->Get(v8_str("f"))));
|
CcTest::global()->Get(v8_str("f"))));
|
||||||
|
|
||||||
Handle<FixedArray> feedback_vector(f->shared()->feedback_vector());
|
Handle<FixedArray> feedback_vector(TypeFeedbackInfo::cast(
|
||||||
|
f->shared()->code()->type_feedback_info())->feedback_vector());
|
||||||
|
|
||||||
CHECK_EQ(2, feedback_vector->length());
|
CHECK_EQ(2, feedback_vector->length());
|
||||||
CHECK(feedback_vector->get(0)->IsJSFunction());
|
CHECK(feedback_vector->get(0)->IsJSFunction());
|
||||||
|
Loading…
Reference in New Issue
Block a user