Reviewers: machenbach, danno,
Message:
Michael is reviewing and learning about alloc. site and hydrogen along the
way.
Danno, would you offer some drive by malevolence? :)
Description:
Simple 0 argument inlining of array constructor
BUG=
Inline calls to "new Array()". The chief difference between the inlined
version
and the stub call is that we need to guard against changes to the
AllocationSite
ElementsKind for the array. If a change occurs, we deopt the method so we
can
try again with up-to-date feedback.
Please review this at https://codereview.chromium.org/18689004/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/hydrogen-instructions.h
M src/hydrogen.h
M src/hydrogen.cc
M test/mjsunit/allocation-site-info.js
Index: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index
ed6ab15c6f695019f1313011095a9807371a26d3..fc8361548a08bf69d9dd31a93b2b166f23322ca1
100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -5341,6 +5341,10 @@ class HObjectAccess {
return HObjectAccess(kInobject, AllocationSiteInfo::kPayloadOffset);
}
+ static HObjectAccess ForPropertyCellValue() {
+ return HObjectAccess(kInobject, PropertyCell::kValueOffset);
+ }
+
// Create an access to an offset in a fixed array header.
static HObjectAccess ForFixedArrayHeader(int offset);
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index
432a6bc5fcd63fe08b81bb60ea30c91747a2218e..7504200072f5e3f58a3da66e19a59712892f7e91
100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -8323,6 +8323,48 @@ static bool
IsAllocationInlineable(Handle<JSFunction> constructor) {
}
+void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) {
+ ASSERT(expr->arguments()->length() == 0);
+ NoObservableSideEffectsScope no_effects(this);
+ VisitForValue(expr->expression());
+ HValue* constructor = Pop();
+ ElementsKind kind = expr->elements_kind();
+ HInstruction* feedback_instruction = AddInstruction(new(zone())
HConstant(
+ kind));
+ HInstruction* cell_instruction = AddInstruction(new(zone()) HConstant(
+ expr->allocation_info_cell()));
+ HInstruction* cell_value =
+ AddInstruction(BuildLoadNamedField(cell_instruction,
+
HObjectAccess::ForPropertyCellValue(),
+ Representation::Smi()));
+
+ // Make sure the runtime contents of the cell match feedback. If not,
+ // deopt. The reason is that a version of the array created before
crankshaft
+ // could transition after this was compiled, and that indicates our
assumption
+ // about the ultimate type of arrays from this allocation site is
outdated.
+ IfBuilder cell_check(this);
+ cell_check.IfCompare(feedback_instruction, cell_value, Token::EQ);
+ cell_check.Then();
+ HValue* new_object;
+ {
+ // Verify we are still calling the array function for our native
context.
+ Handle<JSFunction> array_function(
+ isolate()->global_context()->array_function(), isolate());
+ Add<HCheckFunction>(constructor, array_function);
+
+ // Build the array.
+ JSArrayBuilder array_builder(this,
+ kind,
+ cell_instruction,
+ constructor,
+ DISABLE_ALLOCATION_SITES);
+ new_object = array_builder.AllocateEmptyArray();
+ }
+ cell_check.ElseDeopt();
+ ast_context()->ReturnValue(HInstruction::cast(new_object));
+}
+
+
void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
@@ -8372,11 +8414,18 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew*
expr) {
// argument to the construct call.
Handle<JSFunction> array_function(
isolate()->global_context()->array_function(), isolate());
+ bool use_call_new_array =
expr->target().is_identical_to(array_function);
+ if (use_call_new_array && argument_count == 1) {
+ BuildInlinedCallNewArray(expr);
+ return;
+ }
+
CHECK_ALIVE(VisitArgument(expr->expression()));
HValue* constructor = HPushArgument::cast(Top())->argument();
CHECK_ALIVE(VisitArgumentList(expr->arguments()));
HCallNew* call;
- if (expr->target().is_identical_to(array_function)) {
+
+ if (use_call_new_array) {
Handle<Cell> cell = expr->allocation_info_cell();
Add<HCheckFunction>(constructor, array_function);
call = new(zone()) HCallNewArray(context, constructor,
argument_count,
Index: src/hydrogen.h
diff --git a/src/hydrogen.h b/src/hydrogen.h
index
3ea326296d719c3607e7a3aa4cf2ae4d8d0382e9..fea7e47ad47199bd235117cf2993eed55774dc03
100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -1939,6 +1939,8 @@ class HOptimizedGraphBuilder: public HGraphBuilder,
public AstVisitor {
HValue** operand,
HValue** shift_amount);
+ void BuildInlinedCallNewArray(CallNew* expr);
+
// The translation state of the currently-being-translated function.
FunctionState* function_state_;
Index: test/mjsunit/allocation-site-info.js
diff --git a/test/mjsunit/allocation-site-info.js
b/test/mjsunit/allocation-site-info.js
index
86c28aac63afed2a8c24da2f1fc30e220266adda..e0ec69e7957c06189abe560faae7c568af2911c6
100644
--- a/test/mjsunit/allocation-site-info.js
+++ b/test/mjsunit/allocation-site-info.js
@@ -207,6 +207,38 @@ if (support_smi_only_arrays) {
obj = newarraycase_smiobj(2);
assertKind(elements_kind.fast, obj);
+ // Verify that inlining of zero argument array constructors works for
+ // crankshafted code.
+ function newarraycase_noarg(value) {
+ var a = new Array();
+ a[0] = value;
+ return a;
+ }
+
+ newarraycase_noarg(5);
+ obj = newarraycase_noarg(3.5);
+ assertKind(elements_kind.fast_double, obj);
+ %OptimizeFunctionOnNextCall(newarraycase_noarg);
+ obj = newarraycase_noarg(5);
+ assertKind(elements_kind.fast_double, obj);
+ assertTrue(2 != %GetOptimizationStatus(newarraycase_noarg));
+
+ // We turn off allocation-sites at crankshaft time. But if the
+ // feedback cell changed, we should deopt.
+ %DeoptimizeFunction(newarraycase_noarg);
+ %ClearFunctionTypeFeedback(newarraycase_noarg);
+ newarraycase_noarg(5);
+ obj = newarraycase_noarg(5); // remember obj
+ %OptimizeFunctionOnNextCall(newarraycase_noarg);
+ obj1 = newarraycase_noarg(5);
+ assertKind(elements_kind.fast_smi_only, obj1);
+ assertTrue(2 != %GetOptimizationStatus(newarraycase_noarg));
+ obj[0] = 3.5; // The allocation-site feedback should change
+ obj1 = newarraycase_noarg(5);
+ // We should have deopted and fallen back to full codegen.
+ assertTrue(1 != %GetOptimizationStatus(newarraycase_noarg));
+ assertKind(elements_kind.fast_double, obj1);
+
function newarraycase_length_smidouble(value) {
var a = new Array(3);
a[0] = value;
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.