Currently only simple getter calls are handled (i.e. no calls in count
operations or compound assignments), and deoptimization in the getter is not
handled at all. Because of the latter, we temporarily hide this feature behind a
new flag --inline-accessors, which is false by default.
Review URL: https://chromiumcodereview.appspot.com/
10828066
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12223
ce2b1a6d-e550-0410-aec6-
3dcde31c8c00
if (key->IsPropertyName()) {
VisitForAccumulatorValue(expr->obj());
EmitNamedPropertyLoad(expr);
+ PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
context()->Plug(r0);
} else {
VisitForStackValue(expr->obj());
Expression* key() const { return key_; }
virtual int position() const { return pos_; }
+ // Bailout support.
+ int ReturnId() const { return return_id_; }
+
bool IsStringLength() const { return is_string_length_; }
bool IsStringAccess() const { return is_string_access_; }
bool IsFunctionPrototype() const { return is_function_prototype_; }
obj_(obj),
key_(key),
pos_(pos),
+ return_id_(GetNextId(isolate)),
is_monomorphic_(false),
is_uninitialized_(false),
is_array_length_(false),
Expression* obj_;
Expression* key_;
int pos_;
+ const int return_id_;
SmallMapList receiver_types_;
bool is_monomorphic_ : 1;
"cache optimized code for closures")
DEFINE_bool(inline_construct, true, "inline constructor calls")
DEFINE_bool(inline_arguments, true, "inline functions with arguments object")
+DEFINE_bool(inline_accessors, false, "inline JavaScript accessors")
DEFINE_int(loop_weight, 1, "loop weight for representation inference")
DEFINE_bool(optimize_for_in, true,
Handle<AccessorPair> accessors;
Handle<JSObject> holder;
if (LookupAccessorPair(map, name, &accessors, &holder)) {
- instr = BuildCallGetter(Pop(), map, accessors, holder);
+ AddCheckConstantFunction(holder, Top(), map, true);
+ Handle<JSFunction> getter(JSFunction::cast(accessors->getter()));
+ if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return;
+ AddInstruction(new(zone()) HPushArgument(Pop()));
+ instr = new(zone()) HCallConstantFunction(getter, 1);
} else {
instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map);
}
}
+bool HGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
+ Property* prop) {
+ return TryInline(CALL_AS_METHOD,
+ getter,
+ 0,
+ NULL,
+ prop->id(),
+ prop->ReturnId(),
+ NORMAL_RETURN);
+}
+
+
bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) {
if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
bool TryInlineCall(Call* expr, bool drop_extra = false);
bool TryInlineConstruct(CallNew* expr, HValue* receiver);
+ bool TryInlineGetter(Handle<JSFunction> getter, Property* prop);
bool TryInlineBuiltinMethodCall(Call* expr,
HValue* receiver,
Handle<Map> receiver_map,
VisitForAccumulatorValue(expr->obj());
__ mov(edx, result_register());
EmitNamedPropertyLoad(expr);
+ PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
context()->Plug(eax);
} else {
VisitForStackValue(expr->obj());
if (key->IsPropertyName()) {
VisitForAccumulatorValue(expr->obj());
EmitNamedPropertyLoad(expr);
+ PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
context()->Plug(v0);
} else {
VisitForStackValue(expr->obj());
if (key->IsPropertyName()) {
VisitForAccumulatorValue(expr->obj());
EmitNamedPropertyLoad(expr);
+ PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
context()->Plug(rax);
} else {
VisitForStackValue(expr->obj());