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_HYDROGEN_ACCESSOR(WrapReceiver)
|
||||
|
||||
LOperand* receiver() { return inputs_[0]; }
|
||||
LOperand* function() { return inputs_[1]; }
|
||||
|
@ -3429,19 +3429,21 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
||||
// passed unchanged to builtins and strict-mode functions.
|
||||
Label global_object, result_in_receiver;
|
||||
|
||||
// Do not transform the receiver to object for strict mode
|
||||
// functions.
|
||||
__ ldr(scratch,
|
||||
FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ ldr(scratch,
|
||||
FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
|
||||
__ tst(scratch,
|
||||
Operand(1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize)));
|
||||
__ b(ne, &result_in_receiver);
|
||||
if (!instr->hydrogen()->known_function()) {
|
||||
// Do not transform the receiver to object for strict mode
|
||||
// functions.
|
||||
__ ldr(scratch,
|
||||
FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ ldr(scratch,
|
||||
FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
|
||||
int mask = 1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize);
|
||||
__ tst(scratch, Operand(mask));
|
||||
__ b(ne, &result_in_receiver);
|
||||
|
||||
// Do not transform the receiver to object for builtins.
|
||||
__ tst(scratch, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
|
||||
__ b(ne, &result_in_receiver);
|
||||
// Do not transform the receiver to object for builtins.
|
||||
__ tst(scratch, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
|
||||
__ b(ne, &result_in_receiver);
|
||||
}
|
||||
|
||||
// Normal function. Replace undefined or null with global receiver.
|
||||
__ LoadRoot(scratch, Heap::kNullValueRootIndex);
|
||||
@ -3456,8 +3458,8 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
||||
DeoptimizeIf(eq, instr->environment());
|
||||
__ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
|
||||
DeoptimizeIf(lt, instr->environment());
|
||||
__ b(&result_in_receiver);
|
||||
|
||||
__ b(&result_in_receiver);
|
||||
__ bind(&global_object);
|
||||
__ ldr(result, FieldMemOperand(function, JSFunction::kContextOffset));
|
||||
__ ldr(result,
|
||||
|
@ -3692,6 +3692,8 @@ class HWrapReceiver V8_FINAL : public HTemplateInstruction<2> {
|
||||
public:
|
||||
DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
|
||||
|
||||
virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
|
||||
return Representation::Tagged();
|
||||
}
|
||||
@ -3702,15 +3704,21 @@ class HWrapReceiver V8_FINAL : public HTemplateInstruction<2> {
|
||||
virtual HValue* Canonicalize() V8_OVERRIDE;
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
|
||||
bool known_function() const { return known_function_; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
|
||||
|
||||
private:
|
||||
HWrapReceiver(HValue* receiver, HValue* function) {
|
||||
known_function_ = function->IsConstant() &&
|
||||
HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
|
||||
set_representation(Representation::Tagged());
|
||||
SetOperandAt(0, receiver);
|
||||
SetOperandAt(1, function);
|
||||
SetFlag(kUseGVN);
|
||||
}
|
||||
|
||||
bool known_function_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1287,6 +1287,13 @@ HValue* HGraphBuilder::BuildCheckString(HValue* string) {
|
||||
|
||||
HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -3581,26 +3581,28 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
|
||||
void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
||||
Register receiver = ToRegister(instr->receiver());
|
||||
Register function = ToRegister(instr->function());
|
||||
Register scratch = ToRegister(instr->temp());
|
||||
|
||||
// If the receiver is null or undefined, we have to pass the global
|
||||
// object as a receiver to normal functions. Values have to be
|
||||
// passed unchanged to builtins and strict-mode functions.
|
||||
Label receiver_ok, global_object;
|
||||
Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
|
||||
Register scratch = ToRegister(instr->temp());
|
||||
|
||||
// Do not transform the receiver to object for strict mode
|
||||
// functions.
|
||||
__ mov(scratch,
|
||||
FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset),
|
||||
1 << SharedFunctionInfo::kStrictModeBitWithinByte);
|
||||
__ j(not_equal, &receiver_ok, dist);
|
||||
if (!instr->hydrogen()->known_function()) {
|
||||
// Do not transform the receiver to object for strict mode
|
||||
// functions.
|
||||
__ mov(scratch,
|
||||
FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset),
|
||||
1 << SharedFunctionInfo::kStrictModeBitWithinByte);
|
||||
__ j(not_equal, &receiver_ok, dist);
|
||||
|
||||
// Do not transform the receiver to object for builtins.
|
||||
__ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
|
||||
1 << SharedFunctionInfo::kNativeBitWithinByte);
|
||||
__ j(not_equal, &receiver_ok, dist);
|
||||
// Do not transform the receiver to object for builtins.
|
||||
__ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
|
||||
1 << SharedFunctionInfo::kNativeBitWithinByte);
|
||||
__ j(not_equal, &receiver_ok, dist);
|
||||
}
|
||||
|
||||
// Normal function. Replace undefined or null with global receiver.
|
||||
__ cmp(receiver, factory()->null_value());
|
||||
@ -3613,14 +3615,14 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
||||
DeoptimizeIf(equal, instr->environment());
|
||||
__ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
|
||||
DeoptimizeIf(below, instr->environment());
|
||||
__ jmp(&receiver_ok, Label::kNear);
|
||||
|
||||
__ jmp(&receiver_ok, Label::kNear);
|
||||
__ bind(&global_object);
|
||||
__ mov(receiver, FieldOperand(function, JSFunction::kContextOffset));
|
||||
__ mov(receiver,
|
||||
Operand(receiver, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
|
||||
__ mov(receiver, FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset));
|
||||
|
||||
const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
|
||||
__ mov(receiver, Operand(receiver, global_offset));
|
||||
const int receiver_offset = GlobalObject::kGlobalReceiverOffset;
|
||||
__ mov(receiver, FieldOperand(receiver, receiver_offset));
|
||||
__ bind(&receiver_ok);
|
||||
}
|
||||
|
||||
|
@ -565,6 +565,7 @@ class LWrapReceiver V8_FINAL : public LTemplateInstruction<1, 2, 1> {
|
||||
LOperand* temp() { return temps_[0]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
|
||||
DECLARE_HYDROGEN_ACCESSOR(WrapReceiver)
|
||||
};
|
||||
|
||||
|
||||
|
@ -3161,20 +3161,22 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
||||
Label global_object, receiver_ok;
|
||||
Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
|
||||
|
||||
// Do not transform the receiver to object for strict mode
|
||||
// functions.
|
||||
__ movp(kScratchRegister,
|
||||
FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ testb(FieldOperand(kScratchRegister,
|
||||
SharedFunctionInfo::kStrictModeByteOffset),
|
||||
Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
|
||||
__ j(not_equal, &receiver_ok, dist);
|
||||
if (!instr->hydrogen()->known_function()) {
|
||||
// Do not transform the receiver to object for strict mode
|
||||
// functions.
|
||||
__ movp(kScratchRegister,
|
||||
FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ testb(FieldOperand(kScratchRegister,
|
||||
SharedFunctionInfo::kStrictModeByteOffset),
|
||||
Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
|
||||
__ j(not_equal, &receiver_ok, dist);
|
||||
|
||||
// Do not transform the receiver to object for builtins.
|
||||
__ testb(FieldOperand(kScratchRegister,
|
||||
SharedFunctionInfo::kNativeByteOffset),
|
||||
Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
|
||||
__ j(not_equal, &receiver_ok, dist);
|
||||
// Do not transform the receiver to object for builtins.
|
||||
__ testb(FieldOperand(kScratchRegister,
|
||||
SharedFunctionInfo::kNativeByteOffset),
|
||||
Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
|
||||
__ j(not_equal, &receiver_ok, dist);
|
||||
}
|
||||
|
||||
// Normal function. Replace undefined or null with global receiver.
|
||||
__ CompareRoot(receiver, Heap::kNullValueRootIndex);
|
||||
@ -3187,14 +3189,16 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
|
||||
DeoptimizeIf(is_smi, instr->environment());
|
||||
__ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister);
|
||||
DeoptimizeIf(below, instr->environment());
|
||||
__ jmp(&receiver_ok, Label::kNear);
|
||||
|
||||
__ jmp(&receiver_ok, Label::kNear);
|
||||
__ bind(&global_object);
|
||||
__ movp(receiver, FieldOperand(function, JSFunction::kContextOffset));
|
||||
__ movp(receiver,
|
||||
Operand(receiver, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
|
||||
Operand(receiver,
|
||||
Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
|
||||
__ movp(receiver,
|
||||
FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset));
|
||||
|
||||
__ bind(&receiver_ok);
|
||||
}
|
||||
|
||||
|
@ -552,6 +552,7 @@ class LWrapReceiver V8_FINAL : public LTemplateInstruction<1, 2, 0> {
|
||||
LOperand* function() { return inputs_[1]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
|
||||
DECLARE_HYDROGEN_ACCESSOR(WrapReceiver)
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user