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:
verwaest@chromium.org 2014-01-30 12:52:49 +00:00
parent c3c064360d
commit b73101d539
8 changed files with 71 additions and 45 deletions

View File

@ -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]; }

View File

@ -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,

View File

@ -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_;
};

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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)
};

View File

@ -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);
}

View File

@ -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)
};