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:
parent
7a798fb9e9
commit
4cc800b3cf
@ -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());
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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() {
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
|
@ -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) {
|
||||
|
@ -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) { }
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user