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

Unified Diff: src/hydrogen.cc

Issue 282093009: Emit mementos in crankshaft. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: REBASE. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 36d62d271ce7d1b8451324cc923827a2586b6f26..85a58b391000f1805a6e9ff2f66cf9e07c4a9d3c 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1753,7 +1753,10 @@ HAllocate* HGraphBuilder::BuildAllocate(
// Compute the effective allocation size.
HValue* size = object_size;
if (allocation_mode.CreateAllocationMementos()) {
- size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize));
+ NoObservableSideEffectsScope no_effects(this);
+ size = AddInstruction(
+ HAdd::New(zone(), context(), object_size,
+ Add<HConstant>(AllocationMemento::kSize)));
size->ClearFlag(HValue::kCanOverflow);
}
@@ -2798,6 +2801,7 @@ void HGraphBuilder::BuildCreateAllocationMemento(
HValue* previous_object,
HValue* previous_object_size,
HValue* allocation_site) {
+ NoObservableSideEffectsScope no_effects(this);
ASSERT(allocation_site != NULL);
HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>(
previous_object, previous_object_size, HType::HeapObject());
@@ -5164,7 +5168,9 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
if (!boilerplate.is_null() &&
IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
- AllocationSiteUsageContext usage_context(isolate(), site, false);
+ bool emit_mementos = FLAG_allocation_site_pretenuring &&
+ site->emit_mementos();
+ AllocationSiteUsageContext usage_context(isolate(), site, emit_mementos);
usage_context.EnterNewScope();
literal = BuildFastLiteral(boilerplate, &usage_context);
usage_context.ExitScope(site, boilerplate);
@@ -5321,7 +5327,9 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
if (IsFastLiteral(boilerplate_object,
kMaxFastLiteralDepth,
&max_properties)) {
- AllocationSiteUsageContext usage_context(isolate(), site, false);
+ bool emit_mementos = FLAG_allocation_site_pretenuring &&
+ site->emit_mementos();
+ AllocationSiteUsageContext usage_context(isolate(), site, emit_mementos);
usage_context.EnterNewScope();
literal = BuildFastLiteral(boilerplate_object, &usage_context);
usage_context.ExitScope(site, boilerplate_object);
@@ -8327,16 +8335,17 @@ HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
void HOptimizedGraphBuilder::BuildArrayCall(Expression* expression,
int arguments_count,
HValue* function,
- Handle<AllocationSite> site) {
+ Handle<AllocationSite> site,
+ HAllocationMode mode) {
Add<HCheckValue>(function, array_function());
if (IsCallArrayInlineable(arguments_count, site)) {
- BuildInlinedCallArray(expression, arguments_count, site);
+ BuildInlinedCallArray(expression, arguments_count, mode, site);
return;
}
HInstruction* call = PreProcessCall(New<HCallNewArray>(
- function, arguments_count + 1, site->GetElementsKind()));
+ function, arguments_count + 1, site->GetElementsKind(), mode));
if (expression->IsCall()) {
Drop(1);
}
@@ -8497,13 +8506,15 @@ bool HOptimizedGraphBuilder::TryHandleArrayCall(Call* expr, HValue* function) {
BuildArrayCall(expr,
expr->arguments()->length(),
function,
- site);
+ site,
+ HAllocationMode());
return true;
}
bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr,
- HValue* function) {
+ HValue* function,
+ HAllocationMode mode) {
if (!array_function().is_identical_to(expr->target())) {
return false;
}
@@ -8511,7 +8522,8 @@ bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr,
BuildArrayCall(expr,
expr->arguments()->length(),
function,
- expr->allocation_site());
+ expr->allocation_site(),
+ mode);
return true;
}
@@ -8697,6 +8709,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
void HOptimizedGraphBuilder::BuildInlinedCallArray(
Expression* expression,
int argument_count,
+ HAllocationMode mode,
Handle<AllocationSite> site) {
ASSERT(!site.is_null());
ASSERT(argument_count >= 0 && argument_count <= 1);
@@ -8725,12 +8738,17 @@ void HOptimizedGraphBuilder::BuildInlinedCallArray(
}
}
- // Build the array.
+ // Build the array. Should we emit mementos?
+ AllocationSiteOverrideMode site_mode = mode.CreateAllocationMementos()
+ ? DONT_OVERRIDE
+ : DISABLE_ALLOCATION_SITES;
+
JSArrayBuilder array_builder(this,
kind,
site_instruction,
constructor,
- DISABLE_ALLOCATION_SITES);
+ site_mode);
+
HValue* new_object = argument_count == 0
? array_builder.AllocateEmptyArray()
: BuildAllocateArrayFromLength(&array_builder, Top());
@@ -8796,6 +8814,30 @@ bool HOptimizedGraphBuilder::IsCallArrayInlineable(
}
+void HOptimizedGraphBuilder::InitializeAllocationModeForCallNew(
+ CallNew* expr,
+ HAllocationMode* mode) {
+ if (FLAG_pretenuring_call_new) {
+ if (FLAG_allocation_site_pretenuring) {
+ Handle<AllocationSite> allocation_site = expr->allocation_site();
+ HConstant* site_constant = NULL;
+ // By passing a non-null HConstant AllocationSite to HAllocationMode,
+ // we ensure that a memento will be emitted.
+ if (allocation_site->emit_mementos()) {
+ site_constant = Add<HConstant>(allocation_site);
+ }
+ // Try to use pretenuring feedback.
+ *mode = HAllocationMode(allocation_site, site_constant);
+ // Take a dependency on allocation site.
+ AllocationSite::AddDependentCompilationInfo(allocation_site,
+ AllocationSite::TENURING,
+ top_info());
+ }
+ }
+ // No else case, the mode will be left at it's default.
+}
+
+
void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
@@ -8831,17 +8873,7 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
// Allocate an instance of the implicit receiver object.
HValue* size_in_bytes = Add<HConstant>(instance_size);
HAllocationMode allocation_mode;
- if (FLAG_pretenuring_call_new) {
- if (FLAG_allocation_site_pretenuring) {
- // Try to use pretenuring feedback.
- Handle<AllocationSite> allocation_site = expr->allocation_site();
- allocation_mode = HAllocationMode(allocation_site);
- // Take a dependency on allocation site.
- AllocationSite::AddDependentCompilationInfo(allocation_site,
- AllocationSite::TENURING,
- top_info());
- }
- }
+ InitializeAllocationModeForCallNew(expr, &allocation_mode);
HAllocate* receiver = BuildAllocate(
size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode);
@@ -8893,22 +8925,40 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
// arguments in case inlining failed. What we actually should do is for
// inlining to try to build a subgraph without mutating the parent graph.
HInstruction* instr = current_block()->last();
- do {
+
+ // If we decided to emit a memento for this allocation, we need to
+ // remember the instruction of the HConstant for the site added
+ // in InitializeAllocationModeForCallNew().
+ HValue* delete_to_this_instruction =
+ allocation_mode.CreateAllocationMementos()
+ ? allocation_mode.current_site()
+ : receiver;
+ ASSERT(delete_to_this_instruction != NULL);
+ while (instr != delete_to_this_instruction) {
HInstruction* prev_instr = instr->previous();
instr->DeleteAndReplaceWith(NULL);
instr = prev_instr;
- } while (instr != check);
+ }
+ // initial_map_value->DeleteAndReplaceWith(NULL);
+ if (delete_to_this_instruction == receiver) {
+ receiver->DeleteAndReplaceWith(NULL);
+ }
+ check->DeleteAndReplaceWith(NULL);
environment()->SetExpressionStackAt(receiver_index, function);
- HInstruction* call =
- PreProcessCall(New<HCallNew>(function, argument_count));
+ HInstruction* call = PreProcessCall(
+ New<HCallNew>(function, argument_count, allocation_mode));
return ast_context()->ReturnInstruction(call, expr->id());
} else {
+ HAllocationMode allocation_mode;
+ InitializeAllocationModeForCallNew(expr, &allocation_mode);
+
// The constructor function is both an operand to the instruction and an
// argument to the construct call.
- if (TryHandleArrayCallNew(expr, function)) return;
+ if (TryHandleArrayCallNew(expr, function, allocation_mode)) return;
HInstruction* call =
- PreProcessCall(New<HCallNew>(function, argument_count));
+ PreProcessCall(New<HCallNew>(function, argument_count,
+ allocation_mode));
return ast_context()->ReturnInstruction(call, expr->id());
}
}
@@ -9774,6 +9824,16 @@ HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
allocation_mode = HAllocationMode(allocation_site);
}
+ if (FLAG_allocation_site_pretenuring &&
+ !allocation_site.is_null() &&
+ allocation_site->emit_mementos()) {
+ // This allows crankshaft to continue emitting mementos if a pretenuring
+ // decision wasn't made yet. A dependency is registered on the site in
+ // the BuildBinaryOperation call below.
+ HConstant* site_constant = Add<HConstant>(allocation_site);
+ allocation_mode = HAllocationMode(allocation_site, site_constant);
+ }
+
HValue* result = HGraphBuilder::BuildBinaryOperation(
expr->op(), left, right, left_type, right_type, result_type,
fixed_right_arg, allocation_mode);
@@ -10476,8 +10536,14 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
HType type = instance_type == JS_ARRAY_TYPE
? HType::JSArray() : HType::JSObject();
- HValue* object_size_constant = Add<HConstant>(
- boilerplate_object->map()->instance_size());
+ int instance_size = boilerplate_object->map()->instance_size();
+ bool emit_memento = site_context->ShouldCreateMemento(boilerplate_object);
+ // Should the object allocation include a manually folded memento?
+ int alloc_size = emit_memento
+ ? instance_size + AllocationMemento::kSize
+ : instance_size;
+ HValue* alloc_size_constant = Add<HConstant>(alloc_size);
+ HValue* allocation_site_constant = Add<HConstant>(site_context->current());
PretenureFlag pretenure_flag = NOT_TENURED;
if (FLAG_allocation_site_pretenuring) {
@@ -10487,7 +10553,7 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
site, AllocationSite::TENURING, top_info());
}
- HInstruction* object = Add<HAllocate>(object_size_constant, type,
+ HInstruction* object = Add<HAllocate>(alloc_size_constant, type,
pretenure_flag, instance_type, site_context->current());
// If allocation folding reaches Page::kMaxRegularHeapObjectSize the
@@ -10500,6 +10566,11 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
empty_fixed_array);
BuildEmitObjectHeader(boilerplate_object, object);
+ if (emit_memento) {
+ BuildCreateAllocationMemento(object,
+ Add<HConstant>(instance_size),
+ allocation_site_constant);
+ }
Handle<FixedArrayBase> elements(boilerplate_object->elements());
int elements_size = (elements->length() > 0 &&
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698