Optimize HWrapReceiver
R=dcarney@chromium.org Review URL: https://codereview.chromium.org/135593006 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18945 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
c3c064360d
commit
b73101d539
@ -549,6 +549,7 @@ class LWrapReceiver V8_FINAL : public LTemplateInstruction<1, 2, 0> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
|
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
|
||||||
|
DECLARE_HYDROGEN_ACCESSOR(WrapReceiver)
|
||||||
|
|
||||||
LOperand* receiver() { return inputs_[0]; }
|
LOperand* receiver() { return inputs_[0]; }
|
||||||
LOperand* function() { return inputs_[1]; }
|
LOperand* function() { return inputs_[1]; }
|
||||||
|
@ -3429,19 +3429,21 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
|||||||
// passed unchanged to builtins and strict-mode functions.
|
// passed unchanged to builtins and strict-mode functions.
|
||||||
Label global_object, result_in_receiver;
|
Label global_object, result_in_receiver;
|
||||||
|
|
||||||
|
if (!instr->hydrogen()->known_function()) {
|
||||||
// Do not transform the receiver to object for strict mode
|
// Do not transform the receiver to object for strict mode
|
||||||
// functions.
|
// functions.
|
||||||
__ ldr(scratch,
|
__ ldr(scratch,
|
||||||
FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
|
FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
|
||||||
__ ldr(scratch,
|
__ ldr(scratch,
|
||||||
FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
|
FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
|
||||||
__ tst(scratch,
|
int mask = 1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize);
|
||||||
Operand(1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize)));
|
__ tst(scratch, Operand(mask));
|
||||||
__ b(ne, &result_in_receiver);
|
__ b(ne, &result_in_receiver);
|
||||||
|
|
||||||
// Do not transform the receiver to object for builtins.
|
// Do not transform the receiver to object for builtins.
|
||||||
__ tst(scratch, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
|
__ tst(scratch, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
|
||||||
__ b(ne, &result_in_receiver);
|
__ b(ne, &result_in_receiver);
|
||||||
|
}
|
||||||
|
|
||||||
// Normal function. Replace undefined or null with global receiver.
|
// Normal function. Replace undefined or null with global receiver.
|
||||||
__ LoadRoot(scratch, Heap::kNullValueRootIndex);
|
__ LoadRoot(scratch, Heap::kNullValueRootIndex);
|
||||||
@ -3456,8 +3458,8 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
|||||||
DeoptimizeIf(eq, instr->environment());
|
DeoptimizeIf(eq, instr->environment());
|
||||||
__ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
|
__ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
|
||||||
DeoptimizeIf(lt, instr->environment());
|
DeoptimizeIf(lt, instr->environment());
|
||||||
__ b(&result_in_receiver);
|
|
||||||
|
|
||||||
|
__ b(&result_in_receiver);
|
||||||
__ bind(&global_object);
|
__ bind(&global_object);
|
||||||
__ ldr(result, FieldMemOperand(function, JSFunction::kContextOffset));
|
__ ldr(result, FieldMemOperand(function, JSFunction::kContextOffset));
|
||||||
__ ldr(result,
|
__ ldr(result,
|
||||||
|
@ -3692,6 +3692,8 @@ class HWrapReceiver V8_FINAL : public HTemplateInstruction<2> {
|
|||||||
public:
|
public:
|
||||||
DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
|
DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
|
||||||
|
|
||||||
|
virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
|
||||||
|
|
||||||
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
|
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
|
||||||
return Representation::Tagged();
|
return Representation::Tagged();
|
||||||
}
|
}
|
||||||
@ -3702,15 +3704,21 @@ class HWrapReceiver V8_FINAL : public HTemplateInstruction<2> {
|
|||||||
virtual HValue* Canonicalize() V8_OVERRIDE;
|
virtual HValue* Canonicalize() V8_OVERRIDE;
|
||||||
|
|
||||||
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
|
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
|
||||||
|
bool known_function() const { return known_function_; }
|
||||||
|
|
||||||
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
|
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HWrapReceiver(HValue* receiver, HValue* function) {
|
HWrapReceiver(HValue* receiver, HValue* function) {
|
||||||
|
known_function_ = function->IsConstant() &&
|
||||||
|
HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
|
||||||
set_representation(Representation::Tagged());
|
set_representation(Representation::Tagged());
|
||||||
SetOperandAt(0, receiver);
|
SetOperandAt(0, receiver);
|
||||||
SetOperandAt(1, function);
|
SetOperandAt(1, function);
|
||||||
|
SetFlag(kUseGVN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool known_function_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1287,6 +1287,13 @@ HValue* HGraphBuilder::BuildCheckString(HValue* string) {
|
|||||||
|
|
||||||
HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
|
HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
|
||||||
if (object->type().IsJSObject()) return object;
|
if (object->type().IsJSObject()) return object;
|
||||||
|
if (function->IsConstant() &&
|
||||||
|
HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
|
||||||
|
Handle<JSFunction> f = Handle<JSFunction>::cast(
|
||||||
|
HConstant::cast(function)->handle(isolate()));
|
||||||
|
SharedFunctionInfo* shared = f->shared();
|
||||||
|
if (!shared->is_classic_mode() || shared->native()) return object;
|
||||||
|
}
|
||||||
return Add<HWrapReceiver>(object, function);
|
return Add<HWrapReceiver>(object, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3581,14 +3581,15 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
|
|||||||
void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
||||||
Register receiver = ToRegister(instr->receiver());
|
Register receiver = ToRegister(instr->receiver());
|
||||||
Register function = ToRegister(instr->function());
|
Register function = ToRegister(instr->function());
|
||||||
Register scratch = ToRegister(instr->temp());
|
|
||||||
|
|
||||||
// If the receiver is null or undefined, we have to pass the global
|
// If the receiver is null or undefined, we have to pass the global
|
||||||
// object as a receiver to normal functions. Values have to be
|
// object as a receiver to normal functions. Values have to be
|
||||||
// passed unchanged to builtins and strict-mode functions.
|
// passed unchanged to builtins and strict-mode functions.
|
||||||
Label receiver_ok, global_object;
|
Label receiver_ok, global_object;
|
||||||
Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
|
Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
|
||||||
|
Register scratch = ToRegister(instr->temp());
|
||||||
|
|
||||||
|
if (!instr->hydrogen()->known_function()) {
|
||||||
// Do not transform the receiver to object for strict mode
|
// Do not transform the receiver to object for strict mode
|
||||||
// functions.
|
// functions.
|
||||||
__ mov(scratch,
|
__ mov(scratch,
|
||||||
@ -3601,6 +3602,7 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
|||||||
__ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
|
__ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
|
||||||
1 << SharedFunctionInfo::kNativeBitWithinByte);
|
1 << SharedFunctionInfo::kNativeBitWithinByte);
|
||||||
__ j(not_equal, &receiver_ok, dist);
|
__ j(not_equal, &receiver_ok, dist);
|
||||||
|
}
|
||||||
|
|
||||||
// Normal function. Replace undefined or null with global receiver.
|
// Normal function. Replace undefined or null with global receiver.
|
||||||
__ cmp(receiver, factory()->null_value());
|
__ cmp(receiver, factory()->null_value());
|
||||||
@ -3613,14 +3615,14 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
|||||||
DeoptimizeIf(equal, instr->environment());
|
DeoptimizeIf(equal, instr->environment());
|
||||||
__ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
|
__ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
|
||||||
DeoptimizeIf(below, instr->environment());
|
DeoptimizeIf(below, instr->environment());
|
||||||
__ jmp(&receiver_ok, Label::kNear);
|
|
||||||
|
|
||||||
|
__ jmp(&receiver_ok, Label::kNear);
|
||||||
__ bind(&global_object);
|
__ bind(&global_object);
|
||||||
__ mov(receiver, FieldOperand(function, JSFunction::kContextOffset));
|
__ mov(receiver, FieldOperand(function, JSFunction::kContextOffset));
|
||||||
__ mov(receiver,
|
const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
|
||||||
Operand(receiver, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
|
__ mov(receiver, Operand(receiver, global_offset));
|
||||||
__ mov(receiver, FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset));
|
const int receiver_offset = GlobalObject::kGlobalReceiverOffset;
|
||||||
|
__ mov(receiver, FieldOperand(receiver, receiver_offset));
|
||||||
__ bind(&receiver_ok);
|
__ bind(&receiver_ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,6 +565,7 @@ class LWrapReceiver V8_FINAL : public LTemplateInstruction<1, 2, 1> {
|
|||||||
LOperand* temp() { return temps_[0]; }
|
LOperand* temp() { return temps_[0]; }
|
||||||
|
|
||||||
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
|
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
|
||||||
|
DECLARE_HYDROGEN_ACCESSOR(WrapReceiver)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -3161,6 +3161,7 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
|||||||
Label global_object, receiver_ok;
|
Label global_object, receiver_ok;
|
||||||
Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
|
Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
|
||||||
|
|
||||||
|
if (!instr->hydrogen()->known_function()) {
|
||||||
// Do not transform the receiver to object for strict mode
|
// Do not transform the receiver to object for strict mode
|
||||||
// functions.
|
// functions.
|
||||||
__ movp(kScratchRegister,
|
__ movp(kScratchRegister,
|
||||||
@ -3175,6 +3176,7 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
|||||||
SharedFunctionInfo::kNativeByteOffset),
|
SharedFunctionInfo::kNativeByteOffset),
|
||||||
Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
|
Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
|
||||||
__ j(not_equal, &receiver_ok, dist);
|
__ j(not_equal, &receiver_ok, dist);
|
||||||
|
}
|
||||||
|
|
||||||
// Normal function. Replace undefined or null with global receiver.
|
// Normal function. Replace undefined or null with global receiver.
|
||||||
__ CompareRoot(receiver, Heap::kNullValueRootIndex);
|
__ CompareRoot(receiver, Heap::kNullValueRootIndex);
|
||||||
@ -3187,14 +3189,16 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
|||||||
DeoptimizeIf(is_smi, instr->environment());
|
DeoptimizeIf(is_smi, instr->environment());
|
||||||
__ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister);
|
__ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister);
|
||||||
DeoptimizeIf(below, instr->environment());
|
DeoptimizeIf(below, instr->environment());
|
||||||
__ jmp(&receiver_ok, Label::kNear);
|
|
||||||
|
|
||||||
|
__ jmp(&receiver_ok, Label::kNear);
|
||||||
__ bind(&global_object);
|
__ bind(&global_object);
|
||||||
__ movp(receiver, FieldOperand(function, JSFunction::kContextOffset));
|
__ movp(receiver, FieldOperand(function, JSFunction::kContextOffset));
|
||||||
__ movp(receiver,
|
__ movp(receiver,
|
||||||
Operand(receiver, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
|
Operand(receiver,
|
||||||
|
Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
|
||||||
__ movp(receiver,
|
__ movp(receiver,
|
||||||
FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset));
|
FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset));
|
||||||
|
|
||||||
__ bind(&receiver_ok);
|
__ bind(&receiver_ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,6 +552,7 @@ class LWrapReceiver V8_FINAL : public LTemplateInstruction<1, 2, 0> {
|
|||||||
LOperand* function() { return inputs_[1]; }
|
LOperand* function() { return inputs_[1]; }
|
||||||
|
|
||||||
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
|
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
|
||||||
|
DECLARE_HYDROGEN_ACCESSOR(WrapReceiver)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user