Support %_IsUndetectableObject in crankshaft.

Review URL: http://codereview.chromium.org/6995046

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7856 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
vitalyr@chromium.org 2011-05-11 11:53:43 +00:00
parent 7a798fb9e9
commit 4cc800b3cf
12 changed files with 308 additions and 10 deletions

View File

@ -237,6 +237,13 @@ void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
}
void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if is_undetectable(");
InputAt(0)->PrintTo(stream);
stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
}
void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if has_instance_type(");
InputAt(0)->PrintTo(stream);
@ -1081,6 +1088,12 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
ASSERT(compare->value()->representation().IsTagged());
return new LIsSmiAndBranch(Use(compare->value()));
} else if (v->IsIsUndetectable()) {
HIsUndetectable* compare = HIsUndetectable::cast(v);
ASSERT(compare->value()->representation().IsTagged());
return new LIsUndetectableAndBranch(UseRegisterAtStart(compare->value()),
TempRegister());
} else if (v->IsHasInstanceType()) {
HHasInstanceType* compare = HHasInstanceType::cast(v);
ASSERT(compare->value()->representation().IsTagged());
@ -1531,6 +1544,14 @@ LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) {
}
LInstruction* LChunkBuilder::DoIsUndetectable(HIsUndetectable* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
return DefineAsRegister(new LIsUndetectable(value));
}
LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());

View File

@ -108,12 +108,16 @@ class LCodeGen;
V(InstructionGap) \
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsConstructCall) \
V(IsConstructCallAndBranch) \
V(IsNull) \
V(IsNullAndBranch) \
V(IsObject) \
V(IsObjectAndBranch) \
V(IsSmi) \
V(IsSmiAndBranch) \
V(IsUndetectable) \
V(IsUndetectableAndBranch) \
V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
@ -165,8 +169,6 @@ class LCodeGen;
V(Typeof) \
V(TypeofIs) \
V(TypeofIsAndBranch) \
V(IsConstructCall) \
V(IsConstructCallAndBranch) \
V(UnaryMathOperation) \
V(UnknownOSRValue) \
V(ValueOf)
@ -754,6 +756,31 @@ class LIsSmiAndBranch: public LControlInstruction<1, 0> {
};
class LIsUndetectable: public LTemplateInstruction<1, 1, 0> {
public:
explicit LIsUndetectable(LOperand* value) {
inputs_[0] = value;
}
DECLARE_CONCRETE_INSTRUCTION(IsUndetectable, "is-undetectable")
DECLARE_HYDROGEN_ACCESSOR(IsUndetectable)
};
class LIsUndetectableAndBranch: public LControlInstruction<1, 1> {
public:
explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
inputs_[0] = value;
temps_[0] = temp;
}
DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
"is-undetectable-and-branch")
virtual void PrintDataTo(StringStream* stream);
};
class LHasInstanceType: public LTemplateInstruction<1, 1, 0> {
public:
explicit LHasInstanceType(LOperand* value) {

View File

@ -1774,6 +1774,40 @@ void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
}
void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) {
Register input = ToRegister(instr->InputAt(0));
Register result = ToRegister(instr->result());
ASSERT(instr->hydrogen()->value()->representation().IsTagged());
Label false_label, done;
__ JumpIfSmi(input, &false_label);
__ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset));
__ ldrb(result, FieldMemOperand(result, Map::kBitFieldOffset));
__ tst(result, Operand(1 << Map::kIsUndetectable));
__ b(eq, &false_label);
__ LoadRoot(result, Heap::kTrueValueRootIndex);
__ jmp(&done);
__ bind(&false_label);
__ LoadRoot(result, Heap::kFalseValueRootIndex);
__ bind(&done);
}
void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
Register input = ToRegister(instr->InputAt(0));
Register temp = ToRegister(instr->TempAt(0));
int true_block = chunk_->LookupDestination(instr->true_block_id());
int false_block = chunk_->LookupDestination(instr->false_block_id());
__ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block));
__ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset));
__ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
__ tst(temp, Operand(1 << Map::kIsUndetectable));
EmitBranch(true_block, false_block, ne);
}
static InstanceType TestType(HHasInstanceType* instr) {
InstanceType from = instr->from();
InstanceType to = instr->to();

View File

@ -110,10 +110,11 @@ class LChunkBuilder;
V(InstanceOf) \
V(InstanceOfKnownGlobal) \
V(InvokeFunction) \
V(IsConstructCall) \
V(IsNull) \
V(IsObject) \
V(IsSmi) \
V(IsConstructCall) \
V(IsUndetectable) \
V(JSArrayLength) \
V(LeaveInlined) \
V(LoadContextSlot) \
@ -2469,6 +2470,17 @@ class HIsSmi: public HUnaryPredicate {
};
class HIsUndetectable: public HUnaryPredicate {
public:
explicit HIsUndetectable(HValue* value) : HUnaryPredicate(value) { }
DECLARE_CONCRETE_INSTRUCTION(IsUndetectable)
protected:
virtual bool DataEquals(HValue* other) { return true; }
};
class HIsConstructCall: public HTemplateInstruction<0> {
public:
HIsConstructCall() {

View File

@ -5274,7 +5274,11 @@ void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
return Bailout("inlined runtime function: IsUndetectableObject");
ASSERT(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
HValue* value = Pop();
ast_context()->ReturnInstruction(new(zone()) HIsUndetectable(value),
call->id());
}

View File

@ -1702,6 +1702,44 @@ void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
}
void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) {
Register input = ToRegister(instr->InputAt(0));
Register result = ToRegister(instr->result());
ASSERT(instr->hydrogen()->value()->representation().IsTagged());
Label false_label, done;
STATIC_ASSERT(kSmiTag == 0);
__ test(input, Immediate(kSmiTagMask));
__ j(zero, &false_label, Label::kNear);
__ mov(result, FieldOperand(input, HeapObject::kMapOffset));
__ test_b(FieldOperand(result, Map::kBitFieldOffset),
1 << Map::kIsUndetectable);
__ j(zero, &false_label, Label::kNear);
__ mov(result, factory()->true_value());
__ jmp(&done);
__ bind(&false_label);
__ mov(result, factory()->false_value());
__ bind(&done);
}
void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
Register input = ToRegister(instr->InputAt(0));
Register temp = ToRegister(instr->TempAt(0));
int true_block = chunk_->LookupDestination(instr->true_block_id());
int false_block = chunk_->LookupDestination(instr->false_block_id());
STATIC_ASSERT(kSmiTag == 0);
__ test(input, Immediate(kSmiTagMask));
__ j(zero, chunk_->GetAssemblyLabel(false_block));
__ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
__ test_b(FieldOperand(temp, Map::kBitFieldOffset),
1 << Map::kIsUndetectable);
EmitBranch(true_block, false_block, not_zero);
}
static InstanceType TestType(HHasInstanceType* instr) {
InstanceType from = instr->from();
InstanceType to = instr->to();

View File

@ -239,6 +239,13 @@ void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
}
void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if is_undetectable(");
InputAt(0)->PrintTo(stream);
stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
}
void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if has_instance_type(");
InputAt(0)->PrintTo(stream);
@ -1080,6 +1087,12 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
ASSERT(compare->value()->representation().IsTagged());
return new LIsSmiAndBranch(Use(compare->value()));
} else if (v->IsIsUndetectable()) {
HIsUndetectable* compare = HIsUndetectable::cast(v);
ASSERT(compare->value()->representation().IsTagged());
return new LIsUndetectableAndBranch(UseRegisterAtStart(compare->value()),
TempRegister());
} else if (v->IsHasInstanceType()) {
HHasInstanceType* compare = HHasInstanceType::cast(v);
ASSERT(compare->value()->representation().IsTagged());
@ -1564,6 +1577,14 @@ LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) {
}
LInstruction* LChunkBuilder::DoIsUndetectable(HIsUndetectable* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
return DefineAsRegister(new LIsUndetectable(value));
}
LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());

View File

@ -102,14 +102,16 @@ class LCodeGen;
V(InstructionGap) \
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsConstructCall) \
V(IsConstructCallAndBranch) \
V(IsNull) \
V(IsNullAndBranch) \
V(IsObject) \
V(IsObjectAndBranch) \
V(IsSmi) \
V(IsSmiAndBranch) \
V(IsConstructCall) \
V(IsConstructCallAndBranch) \
V(IsUndetectable) \
V(IsUndetectableAndBranch) \
V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
@ -743,6 +745,31 @@ class LIsSmiAndBranch: public LControlInstruction<1, 0> {
};
class LIsUndetectable: public LTemplateInstruction<1, 1, 0> {
public:
explicit LIsUndetectable(LOperand* value) {
inputs_[0] = value;
}
DECLARE_CONCRETE_INSTRUCTION(IsUndetectable, "is-undetectable")
DECLARE_HYDROGEN_ACCESSOR(IsUndetectable)
};
class LIsUndetectableAndBranch: public LControlInstruction<1, 1> {
public:
explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
inputs_[0] = value;
temps_[0] = temp;
}
DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
"is-undetectable-and-branch")
virtual void PrintDataTo(StringStream* stream);
};
class LHasInstanceType: public LTemplateInstruction<1, 1, 0> {
public:
explicit LHasInstanceType(LOperand* value) {

View File

@ -1723,6 +1723,40 @@ void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
}
void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) {
Register input = ToRegister(instr->InputAt(0));
Register result = ToRegister(instr->result());
ASSERT(instr->hydrogen()->value()->representation().IsTagged());
Label false_label, done;
__ JumpIfSmi(input, &false_label);
__ movq(result, FieldOperand(input, HeapObject::kMapOffset));
__ testb(FieldOperand(result, Map::kBitFieldOffset),
Immediate(1 << Map::kIsUndetectable));
__ j(zero, &false_label);
__ LoadRoot(result, Heap::kTrueValueRootIndex);
__ jmp(&done);
__ bind(&false_label);
__ LoadRoot(result, Heap::kFalseValueRootIndex);
__ bind(&done);
}
void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
Register input = ToRegister(instr->InputAt(0));
Register temp = ToRegister(instr->TempAt(0));
int true_block = chunk_->LookupDestination(instr->true_block_id());
int false_block = chunk_->LookupDestination(instr->false_block_id());
__ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block));
__ movq(temp, FieldOperand(input, HeapObject::kMapOffset));
__ testb(FieldOperand(temp, Map::kBitFieldOffset),
Immediate(1 << Map::kIsUndetectable));
EmitBranch(true_block, false_block, not_zero);
}
static InstanceType TestType(HHasInstanceType* instr) {
InstanceType from = instr->from();
InstanceType to = instr->to();

View File

@ -239,6 +239,13 @@ void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
}
void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if is_undetectable(");
InputAt(0)->PrintTo(stream);
stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
}
void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if has_instance_type(");
InputAt(0)->PrintTo(stream);
@ -1079,6 +1086,12 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
ASSERT(compare->value()->representation().IsTagged());
return new LIsSmiAndBranch(Use(compare->value()));
} else if (v->IsIsUndetectable()) {
HIsUndetectable* compare = HIsUndetectable::cast(v);
ASSERT(compare->value()->representation().IsTagged());
return new LIsUndetectableAndBranch(UseRegisterAtStart(compare->value()),
TempRegister());
} else if (v->IsHasInstanceType()) {
HHasInstanceType* compare = HHasInstanceType::cast(v);
ASSERT(compare->value()->representation().IsTagged());
@ -1538,6 +1551,14 @@ LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) {
}
LInstruction* LChunkBuilder::DoIsUndetectable(HIsUndetectable* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
return DefineAsRegister(new LIsUndetectable(value));
}
LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());

View File

@ -108,18 +108,23 @@ class LCodeGen;
V(InstructionGap) \
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsConstructCall) \
V(IsConstructCallAndBranch) \
V(IsNull) \
V(IsNullAndBranch) \
V(IsObject) \
V(IsObjectAndBranch) \
V(IsSmi) \
V(IsSmiAndBranch) \
V(IsUndetectable) \
V(IsUndetectableAndBranch) \
V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
V(LoadElements) \
V(LoadExternalArrayPointer) \
V(LoadFunctionPrototype) \
V(LoadGlobalCell) \
V(LoadGlobalGeneric) \
V(LoadKeyedFastElement) \
@ -128,7 +133,6 @@ class LCodeGen;
V(LoadNamedField) \
V(LoadNamedFieldPolymorphic) \
V(LoadNamedGeneric) \
V(LoadFunctionPrototype) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
@ -160,13 +164,11 @@ class LCodeGen;
V(StringLength) \
V(SubI) \
V(TaggedToI) \
V(ToFastProperties) \
V(Throw) \
V(ToFastProperties) \
V(Typeof) \
V(TypeofIs) \
V(TypeofIsAndBranch) \
V(IsConstructCall) \
V(IsConstructCallAndBranch) \
V(UnaryMathOperation) \
V(UnknownOSRValue) \
V(ValueOf)
@ -738,6 +740,31 @@ class LIsSmiAndBranch: public LControlInstruction<1, 0> {
};
class LIsUndetectable: public LTemplateInstruction<1, 1, 0> {
public:
explicit LIsUndetectable(LOperand* value) {
inputs_[0] = value;
}
DECLARE_CONCRETE_INSTRUCTION(IsUndetectable, "is-undetectable")
DECLARE_HYDROGEN_ACCESSOR(IsUndetectable)
};
class LIsUndetectableAndBranch: public LControlInstruction<1, 1> {
public:
explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
inputs_[0] = value;
temps_[0] = temp;
}
DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
"is-undetectable-and-branch")
virtual void PrintDataTo(StringStream* stream);
};
class LHasInstanceType: public LTemplateInstruction<1, 1, 0> {
public:
explicit LHasInstanceType(LOperand* value) {

View File

@ -3940,6 +3940,38 @@ THREADED_TEST(UndetectableString) {
}
TEST(UndetectableOptimized) {
i::FLAG_allow_natives_syntax = true;
v8::HandleScope scope;
LocalContext env;
Local<String> obj = String::NewUndetectable("foo");
env->Global()->Set(v8_str("undetectable"), obj);
env->Global()->Set(v8_str("detectable"), v8_str("bar"));
ExpectString(
"function testBranch() {"
" if (!%_IsUndetectableObject(undetectable)) throw 1;"
" if (%_IsUndetectableObject(detectable)) throw 2;"
"}\n"
"function testBool() {"
" var b1 = !%_IsUndetectableObject(undetectable);"
" var b2 = %_IsUndetectableObject(detectable);"
" if (b1) throw 3;"
" if (b2) throw 4;"
" return b1 == b2;"
"}\n"
"%OptimizeFunctionOnNextCall(testBranch);"
"%OptimizeFunctionOnNextCall(testBool);"
"for (var i = 0; i < 10; i++) {"
" testBranch();"
" testBool();"
"}\n"
"\"PASS\"",
"PASS");
}
template <typename T> static void USE(T) { }