}
-void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
- stream->Add("if is_object(");
- value()->PrintTo(stream);
- stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
-}
-
-
void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if is_string(");
value()->PrintTo(stream);
}
-LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
- DCHECK(instr->value()->representation().IsTagged());
- LOperand* value = UseRegisterAtStart(instr->value());
- LOperand* temp = TempRegister();
- return new(zone()) LIsObjectAndBranch(value, temp);
-}
-
-
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
DCHECK(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsConstructCallAndBranch) \
- V(IsObjectAndBranch) \
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
};
-class LIsObjectAndBranch final : public LControlInstruction<1, 1> {
- public:
- LIsObjectAndBranch(LOperand* value, LOperand* temp) {
- inputs_[0] = value;
- temps_[0] = temp;
- }
-
- LOperand* value() { return inputs_[0]; }
- LOperand* temp() { return temps_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
- DECLARE_HYDROGEN_ACCESSOR(IsObjectAndBranch)
-
- void PrintDataTo(StringStream* stream) override;
-};
-
-
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
public:
LIsStringAndBranch(LOperand* value, LOperand* temp) {
}
-Condition LCodeGen::EmitIsObject(Register input,
- Register temp1,
- Label* is_not_object,
- Label* is_object) {
- Register temp2 = scratch0();
- __ JumpIfSmi(input, is_not_object);
-
- __ LoadRoot(temp2, Heap::kNullValueRootIndex);
- __ cmp(input, temp2);
- __ b(eq, is_object);
-
- // Load map.
- __ ldr(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined.
- __ ldrb(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset));
- __ tst(temp2, Operand(1 << Map::kIsUndetectable));
- __ b(ne, is_not_object);
-
- // Load instance type and check that it is in object type range.
- __ ldrb(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset));
- __ cmp(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
- __ b(lt, is_not_object);
- __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
- return le;
-}
-
-
-void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
- Register reg = ToRegister(instr->value());
- Register temp1 = ToRegister(instr->temp());
-
- Condition true_cond =
- EmitIsObject(reg, temp1,
- instr->FalseLabel(chunk_), instr->TrueLabel(chunk_));
-
- EmitBranch(instr, true_cond);
-}
-
-
Condition LCodeGen::EmitIsString(Register input,
Register temp1,
Label* is_not_string,
Register input,
Handle<String> type_name);
- // Emits optimized code for %_IsObject(x). Preserves input register.
- // Returns the condition on which a final split to
- // true and false label should be made, to optimize fallthrough.
- Condition EmitIsObject(Register input,
- Register temp1,
- Label* is_not_object,
- Label* is_object);
-
// Emits optimized code for %_IsString(x). Preserves input register.
// Returns the condition on which a final split to
// true and false label should be made, to optimize fallthrough.
}
-void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
- stream->Add("if is_object(");
- value()->PrintTo(stream);
- stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
-}
-
-
void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if is_string(");
value()->PrintTo(stream);
}
-LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
- DCHECK(instr->value()->representation().IsTagged());
- LOperand* value = UseRegisterAtStart(instr->value());
- LOperand* temp1 = TempRegister();
- LOperand* temp2 = TempRegister();
- return new(zone()) LIsObjectAndBranch(value, temp1, temp2);
-}
-
-
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
DCHECK(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsConstructCallAndBranch) \
- V(IsObjectAndBranch) \
V(IsSmiAndBranch) \
V(IsStringAndBranch) \
V(IsUndetectableAndBranch) \
};
-class LIsObjectAndBranch final : public LControlInstruction<1, 2> {
- public:
- LIsObjectAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
- inputs_[0] = value;
- temps_[0] = temp1;
- temps_[1] = temp2;
- }
-
- LOperand* value() { return inputs_[0]; }
- LOperand* temp1() { return temps_[0]; }
- LOperand* temp2() { return temps_[1]; }
-
- DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
- DECLARE_HYDROGEN_ACCESSOR(IsObjectAndBranch)
-
- void PrintDataTo(StringStream* stream) override;
-};
-
-
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
public:
LIsStringAndBranch(LOperand* value, LOperand* temp) {
}
-void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
- Label* is_object = instr->TrueLabel(chunk_);
- Label* is_not_object = instr->FalseLabel(chunk_);
- Register value = ToRegister(instr->value());
- Register map = ToRegister(instr->temp1());
- Register scratch = ToRegister(instr->temp2());
-
- __ JumpIfSmi(value, is_not_object);
- __ JumpIfRoot(value, Heap::kNullValueRootIndex, is_object);
-
- __ Ldr(map, FieldMemOperand(value, HeapObject::kMapOffset));
-
- // Check for undetectable objects.
- __ Ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset));
- __ TestAndBranchIfAnySet(scratch, 1 << Map::kIsUndetectable, is_not_object);
-
- // Check that instance type is in object type range.
- __ IsInstanceJSObjectType(map, scratch, NULL);
- // Flags have been updated by IsInstanceJSObjectType. We can now test the
- // flags for "le" condition to check if the object's type is a valid
- // JS object type.
- EmitBranch(instr, le);
-}
-
-
Condition LCodeGen::EmitIsString(Register input,
Register temp1,
Label* is_not_string,
}
-void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ JumpIfSmi(r0, if_false);
- __ LoadRoot(ip, Heap::kNullValueRootIndex);
- __ cmp(r0, ip);
- __ b(eq, if_true);
- __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined when tested with typeof.
- __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
- __ tst(r1, Operand(1 << Map::kIsUndetectable));
- __ b(ne, if_false);
- __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset));
- __ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
- __ b(lt, if_false);
- __ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(le, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
}
-void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ JumpIfSmi(x0, if_false);
- __ JumpIfRoot(x0, Heap::kNullValueRootIndex, if_true);
- __ Ldr(x10, FieldMemOperand(x0, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined when tested with typeof.
- __ Ldrb(x11, FieldMemOperand(x10, Map::kBitFieldOffset));
- __ Tbnz(x11, Map::kIsUndetectable, if_false);
- __ Ldrb(x12, FieldMemOperand(x10, Map::kInstanceTypeOffset));
- __ Cmp(x12, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
- __ B(lt, if_false);
- __ Cmp(x12, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(le, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
F(OneByteSeqStringSetChar) \
F(TwoByteSeqStringSetChar) \
F(ObjectEquals) \
- F(IsObject) \
F(IsFunction) \
F(IsSpecObject) \
F(IsSimdValue) \
}
-void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ JumpIfSmi(eax, if_false);
- __ cmp(eax, isolate()->factory()->null_value());
- __ j(equal, if_true);
- __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined when tested with typeof.
- __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset));
- __ test(ecx, Immediate(1 << Map::kIsUndetectable));
- __ j(not_zero, if_false);
- __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset));
- __ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
- __ j(below, if_false);
- __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(below_equal, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
}
-void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ JumpIfSmi(v0, if_false);
- __ LoadRoot(at, Heap::kNullValueRootIndex);
- __ Branch(if_true, eq, v0, Operand(at));
- __ lw(a2, FieldMemOperand(v0, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined when tested with typeof.
- __ lbu(a1, FieldMemOperand(a2, Map::kBitFieldOffset));
- __ And(at, a1, Operand(1 << Map::kIsUndetectable));
- __ Branch(if_false, ne, at, Operand(zero_reg));
- __ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset));
- __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE),
- if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
}
-void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ JumpIfSmi(v0, if_false);
- __ LoadRoot(at, Heap::kNullValueRootIndex);
- __ Branch(if_true, eq, v0, Operand(at));
- __ ld(a2, FieldMemOperand(v0, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined when tested with typeof.
- __ lbu(a1, FieldMemOperand(a2, Map::kBitFieldOffset));
- __ And(at, a1, Operand(1 << Map::kIsUndetectable));
- __ Branch(if_false, ne, at, Operand(zero_reg));
- __ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset));
- __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE),
- if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
}
-void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
- &if_false, &fall_through);
-
- __ JumpIfSmi(r3, if_false);
- __ LoadRoot(ip, Heap::kNullValueRootIndex);
- __ cmp(r3, ip);
- __ beq(if_true);
- __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined when tested with typeof.
- __ lbz(r4, FieldMemOperand(r5, Map::kBitFieldOffset));
- __ andi(r0, r4, Operand(1 << Map::kIsUndetectable));
- __ bne(if_false, cr0);
- __ lbz(r4, FieldMemOperand(r5, Map::kInstanceTypeOffset));
- __ cmpi(r4, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
- __ blt(if_false);
- __ cmpi(r4, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(le, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
}
-void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ JumpIfSmi(rax, if_false);
- __ CompareRoot(rax, Heap::kNullValueRootIndex);
- __ j(equal, if_true);
- __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined when tested with typeof.
- __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
- Immediate(1 << Map::kIsUndetectable));
- __ j(not_zero, if_false);
- __ movzxbp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
- __ cmpp(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
- __ j(below, if_false);
- __ cmpp(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(below_equal, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
}
-void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ JumpIfSmi(eax, if_false);
- __ cmp(eax, isolate()->factory()->null_value());
- __ j(equal, if_true);
- __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined when tested with typeof.
- __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset));
- __ test(ecx, Immediate(1 << Map::kIsUndetectable));
- __ j(not_zero, if_false);
- __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset));
- __ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
- __ j(below, if_false);
- __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(below_equal, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
case HValue::kInstanceOf:
case HValue::kIsConstructCallAndBranch:
case HValue::kHasInPrototypeChainAndBranch:
- case HValue::kIsObjectAndBranch:
case HValue::kIsSmiAndBranch:
case HValue::kIsStringAndBranch:
case HValue::kIsUndetectableAndBranch:
}
-bool ConstantIsObject(HConstant* constant, Isolate* isolate) {
- if (constant->HasNumberValue()) return false;
- if (constant->GetUnique().IsKnownGlobal(isolate->heap()->null_value())) {
- return true;
- }
- if (constant->IsUndetectable()) return false;
- InstanceType type = constant->GetInstanceType();
- return (FIRST_NONCALLABLE_SPEC_OBJECT_TYPE <= type) &&
- (type <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
-}
-
-
-bool HIsObjectAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
- if (FLAG_fold_constants && value()->IsConstant()) {
- *block = ConstantIsObject(HConstant::cast(value()), isolate())
- ? FirstSuccessor() : SecondSuccessor();
- return true;
- }
- *block = NULL;
- return false;
-}
-
-
bool HIsStringAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
if (known_successor_index() != kNoKnownSuccessorIndex) {
*block = SuccessorAt(known_successor_index());
V(InvokeFunction) \
V(IsConstructCallAndBranch) \
V(HasInPrototypeChainAndBranch) \
- V(IsObjectAndBranch) \
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
};
-class HIsObjectAndBranch final : public HUnaryControlInstruction {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HIsObjectAndBranch, HValue*);
- DECLARE_INSTRUCTION_FACTORY_P3(HIsObjectAndBranch, HValue*,
- HBasicBlock*, HBasicBlock*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- bool KnownSuccessorBlock(HBasicBlock** block) override;
-
- DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
-
- private:
- HIsObjectAndBranch(HValue* value,
- HBasicBlock* true_target = NULL,
- HBasicBlock* false_target = NULL)
- : HUnaryControlInstruction(value, true_target, false_target) {}
-};
-
-
class HIsStringAndBranch final : public HUnaryControlInstruction {
public:
DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
}
-void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
- DCHECK(call->arguments()->length() == 1);
- CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
- HValue* value = Pop();
- HIsObjectAndBranch* result = New<HIsObjectAndBranch>(value);
- return ast_context()->ReturnControl(result, call->id());
-}
-
-
void HOptimizedGraphBuilder::GenerateToObject(CallRuntime* call) {
DCHECK_EQ(1, call->arguments()->length());
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
F(OneByteSeqStringSetChar) \
F(TwoByteSeqStringSetChar) \
F(ObjectEquals) \
- F(IsObject) \
F(ToObject) \
F(IsFunction) \
F(IsSpecObject) \
}
-Condition LCodeGen::EmitIsObject(Register input,
- Register temp1,
- Label* is_not_object,
- Label* is_object) {
- __ JumpIfSmi(input, is_not_object);
-
- __ cmp(input, isolate()->factory()->null_value());
- __ j(equal, is_object);
-
- __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined.
- __ test_b(FieldOperand(temp1, Map::kBitFieldOffset),
- 1 << Map::kIsUndetectable);
- __ j(not_zero, is_not_object);
-
- __ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset));
- __ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
- __ j(below, is_not_object);
- __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
- return below_equal;
-}
-
-
-void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
- Register reg = ToRegister(instr->value());
- Register temp = ToRegister(instr->temp());
-
- Condition true_cond = EmitIsObject(
- reg, temp, instr->FalseLabel(chunk_), instr->TrueLabel(chunk_));
-
- EmitBranch(instr, true_cond);
-}
-
-
Condition LCodeGen::EmitIsString(Register input,
Register temp1,
Label* is_not_string,
// true and false label should be made, to optimize fallthrough.
Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input);
- // Emits optimized code for %_IsObject(x). Preserves input register.
- // Returns the condition on which a final split to
- // true and false label should be made, to optimize fallthrough.
- Condition EmitIsObject(Register input,
- Register temp1,
- Label* is_not_object,
- Label* is_object);
-
// Emits optimized code for %_IsString(x). Preserves input register.
// Returns the condition on which a final split to
// true and false label should be made, to optimize fallthrough.
}
-void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
- stream->Add("if is_object(");
- value()->PrintTo(stream);
- stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
-}
-
-
void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if is_string(");
value()->PrintTo(stream);
}
-LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
- DCHECK(instr->value()->representation().IsSmiOrTagged());
- LOperand* temp = TempRegister();
- return new(zone()) LIsObjectAndBranch(UseRegister(instr->value()), temp);
-}
-
-
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
DCHECK(instr->value()->representation().IsTagged());
LOperand* temp = TempRegister();
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsConstructCallAndBranch) \
- V(IsObjectAndBranch) \
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
};
-class LIsObjectAndBranch final : public LControlInstruction<1, 1> {
- public:
- LIsObjectAndBranch(LOperand* value, LOperand* temp) {
- inputs_[0] = value;
- temps_[0] = temp;
- }
-
- LOperand* value() { return inputs_[0]; }
- LOperand* temp() { return temps_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
-
- void PrintDataTo(StringStream* stream) override;
-};
-
-
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
public:
LIsStringAndBranch(LOperand* value, LOperand* temp) {
macro IS_STRING(arg) = (typeof(arg) === 'string');
macro IS_BOOLEAN(arg) = (typeof(arg) === 'boolean');
macro IS_SYMBOL(arg) = (typeof(arg) === 'symbol');
-macro IS_OBJECT(arg) = (%_IsObject(arg));
+macro IS_OBJECT(arg) = (typeof(arg) === 'object');
macro IS_ARRAY(arg) = (%_IsArray(arg));
macro IS_DATE(arg) = (%_IsDate(arg));
macro IS_FUNCTION(arg) = (%_IsFunction(arg));
}
-Condition LCodeGen::EmitIsObject(Register input,
- Register temp1,
- Register temp2,
- Label* is_not_object,
- Label* is_object) {
- __ JumpIfSmi(input, is_not_object);
-
- __ LoadRoot(temp2, Heap::kNullValueRootIndex);
- __ Branch(is_object, eq, input, Operand(temp2));
-
- // Load map.
- __ lw(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined.
- __ lbu(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset));
- __ And(temp2, temp2, Operand(1 << Map::kIsUndetectable));
- __ Branch(is_not_object, ne, temp2, Operand(zero_reg));
-
- // Load instance type and check that it is in object type range.
- __ lbu(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset));
- __ Branch(is_not_object,
- lt, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
-
- return le;
-}
-
-
-void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
- Register reg = ToRegister(instr->value());
- Register temp1 = ToRegister(instr->temp());
- Register temp2 = scratch0();
-
- Condition true_cond =
- EmitIsObject(reg, temp1, temp2,
- instr->FalseLabel(chunk_), instr->TrueLabel(chunk_));
-
- EmitBranch(instr, true_cond, temp2,
- Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
-}
-
-
Condition LCodeGen::EmitIsString(Register input,
Register temp1,
Label* is_not_string,
Register* cmp1,
Operand* cmp2);
- // Emits optimized code for %_IsObject(x). Preserves input register.
- // Returns the condition on which a final split to
- // true and false label should be made, to optimize fallthrough.
- Condition EmitIsObject(Register input,
- Register temp1,
- Register temp2,
- Label* is_not_object,
- Label* is_object);
-
// Emits optimized code for %_IsString(x). Preserves input register.
// Returns the condition on which a final split to
// true and false label should be made, to optimize fallthrough.
}
-void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
- stream->Add("if is_object(");
- value()->PrintTo(stream);
- stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
-}
-
-
void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if is_string(");
value()->PrintTo(stream);
}
-LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
- DCHECK(instr->value()->representation().IsTagged());
- LOperand* temp = TempRegister();
- return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()),
- temp);
-}
-
-
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
DCHECK(instr->value()->representation().IsTagged());
LOperand* temp = TempRegister();
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsConstructCallAndBranch) \
- V(IsObjectAndBranch) \
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
};
-class LIsObjectAndBranch final : public LControlInstruction<1, 1> {
- public:
- LIsObjectAndBranch(LOperand* value, LOperand* temp) {
- inputs_[0] = value;
- temps_[0] = temp;
- }
-
- LOperand* value() { return inputs_[0]; }
- LOperand* temp() { return temps_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
- DECLARE_HYDROGEN_ACCESSOR(IsObjectAndBranch)
-
- void PrintDataTo(StringStream* stream) override;
-};
-
-
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
public:
LIsStringAndBranch(LOperand* value, LOperand* temp) {
}
-Condition LCodeGen::EmitIsObject(Register input,
- Register temp1,
- Register temp2,
- Label* is_not_object,
- Label* is_object) {
- __ JumpIfSmi(input, is_not_object);
-
- __ LoadRoot(temp2, Heap::kNullValueRootIndex);
- __ Branch(is_object, eq, input, Operand(temp2));
-
- // Load map.
- __ ld(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined.
- __ lbu(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset));
- __ And(temp2, temp2, Operand(1 << Map::kIsUndetectable));
- __ Branch(is_not_object, ne, temp2, Operand(zero_reg));
-
- // Load instance type and check that it is in object type range.
- __ lbu(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset));
- __ Branch(is_not_object,
- lt, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
-
- return le;
-}
-
-
-void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
- Register reg = ToRegister(instr->value());
- Register temp1 = ToRegister(instr->temp());
- Register temp2 = scratch0();
-
- Condition true_cond =
- EmitIsObject(reg, temp1, temp2,
- instr->FalseLabel(chunk_), instr->TrueLabel(chunk_));
-
- EmitBranch(instr, true_cond, temp2,
- Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
-}
-
-
Condition LCodeGen::EmitIsString(Register input,
Register temp1,
Label* is_not_string,
Register* cmp1,
Operand* cmp2);
- // Emits optimized code for %_IsObject(x). Preserves input register.
- // Returns the condition on which a final split to
- // true and false label should be made, to optimize fallthrough.
- Condition EmitIsObject(Register input,
- Register temp1,
- Register temp2,
- Label* is_not_object,
- Label* is_object);
-
// Emits optimized code for %_IsString(x). Preserves input register.
// Returns the condition on which a final split to
// true and false label should be made, to optimize fallthrough.
}
-void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
- stream->Add("if is_object(");
- value()->PrintTo(stream);
- stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
-}
-
-
void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if is_string(");
value()->PrintTo(stream);
}
-LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
- DCHECK(instr->value()->representation().IsTagged());
- LOperand* temp = TempRegister();
- return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()),
- temp);
-}
-
-
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
DCHECK(instr->value()->representation().IsTagged());
LOperand* temp = TempRegister();
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsConstructCallAndBranch) \
- V(IsObjectAndBranch) \
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
};
-class LIsObjectAndBranch final : public LControlInstruction<1, 1> {
- public:
- LIsObjectAndBranch(LOperand* value, LOperand* temp) {
- inputs_[0] = value;
- temps_[0] = temp;
- }
-
- LOperand* value() { return inputs_[0]; }
- LOperand* temp() { return temps_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
- DECLARE_HYDROGEN_ACCESSOR(IsObjectAndBranch)
-
- void PrintDataTo(StringStream* stream) override;
-};
-
-
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
public:
LIsStringAndBranch(LOperand* value, LOperand* temp) {
}
-Condition LCodeGen::EmitIsObject(Register input, Register temp1,
- Label* is_not_object, Label* is_object) {
- Register temp2 = scratch0();
- __ JumpIfSmi(input, is_not_object);
-
- __ LoadRoot(temp2, Heap::kNullValueRootIndex);
- __ cmp(input, temp2);
- __ beq(is_object);
-
- // Load map.
- __ LoadP(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined.
- __ lbz(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset));
- __ TestBit(temp2, Map::kIsUndetectable, r0);
- __ bne(is_not_object, cr0);
-
- // Load instance type and check that it is in object type range.
- __ lbz(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset));
- __ cmpi(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
- __ blt(is_not_object);
- __ cmpi(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
- return le;
-}
-
-
-void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
- Register reg = ToRegister(instr->value());
- Register temp1 = ToRegister(instr->temp());
-
- Condition true_cond = EmitIsObject(reg, temp1, instr->FalseLabel(chunk_),
- instr->TrueLabel(chunk_));
-
- EmitBranch(instr, true_cond);
-}
-
-
Condition LCodeGen::EmitIsString(Register input, Register temp1,
Label* is_not_string,
SmiCheck check_needed = INLINE_SMI_CHECK) {
Condition EmitTypeofIs(Label* true_label, Label* false_label, Register input,
Handle<String> type_name);
- // Emits optimized code for %_IsObject(x). Preserves input register.
- // Returns the condition on which a final split to
- // true and false label should be made, to optimize fallthrough.
- Condition EmitIsObject(Register input, Register temp1, Label* is_not_object,
- Label* is_object);
-
// Emits optimized code for %_IsString(x). Preserves input register.
// Returns the condition on which a final split to
// true and false label should be made, to optimize fallthrough.
}
-void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
- stream->Add("if is_object(");
- value()->PrintTo(stream);
- stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
-}
-
-
void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if is_string(");
value()->PrintTo(stream);
}
-LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
- DCHECK(instr->value()->representation().IsTagged());
- LOperand* value = UseRegisterAtStart(instr->value());
- LOperand* temp = TempRegister();
- return new (zone()) LIsObjectAndBranch(value, temp);
-}
-
-
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
DCHECK(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsConstructCallAndBranch) \
- V(IsObjectAndBranch) \
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
};
-class LIsObjectAndBranch final : public LControlInstruction<1, 1> {
- public:
- LIsObjectAndBranch(LOperand* value, LOperand* temp) {
- inputs_[0] = value;
- temps_[0] = temp;
- }
-
- LOperand* value() { return inputs_[0]; }
- LOperand* temp() { return temps_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
- DECLARE_HYDROGEN_ACCESSOR(IsObjectAndBranch)
-
- void PrintDataTo(StringStream* stream) override;
-};
-
-
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
public:
LIsStringAndBranch(LOperand* value, LOperand* temp) {
}
-RUNTIME_FUNCTION(Runtime_IsObject) {
- SealHandleScope shs(isolate);
- DCHECK(args.length() == 1);
- CONVERT_ARG_CHECKED(Object, obj, 0);
- if (!obj->IsHeapObject()) return isolate->heap()->false_value();
- if (obj->IsNull()) return isolate->heap()->true_value();
- if (obj->IsUndetectableObject()) return isolate->heap()->false_value();
- Map* map = HeapObject::cast(obj)->map();
- bool is_non_callable_spec_object =
- map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
- map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE;
- return isolate->heap()->ToBoolean(is_non_callable_spec_object);
-}
-
-
RUNTIME_FUNCTION(Runtime_IsSpecObject) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
F(HeapObjectGetMap, 1, 1) \
F(MapGetInstanceType, 1, 1) \
F(ObjectEquals, 2, 1) \
- F(IsObject, 1, 1) \
F(IsSpecObject, 1, 1) \
F(IsStrong, 1, 1) \
F(ClassOf, 1, 1) \
}
-Condition LCodeGen::EmitIsObject(Register input,
- Label* is_not_object,
- Label* is_object) {
- DCHECK(!input.is(kScratchRegister));
-
- __ JumpIfSmi(input, is_not_object);
-
- __ CompareRoot(input, Heap::kNullValueRootIndex);
- __ j(equal, is_object);
-
- __ movp(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined.
- __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset),
- Immediate(1 << Map::kIsUndetectable));
- __ j(not_zero, is_not_object);
-
- __ movzxbl(kScratchRegister,
- FieldOperand(kScratchRegister, Map::kInstanceTypeOffset));
- __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
- __ j(below, is_not_object);
- __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
- return below_equal;
-}
-
-
-void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
- Register reg = ToRegister(instr->value());
-
- Condition true_cond = EmitIsObject(
- reg, instr->FalseLabel(chunk_), instr->TrueLabel(chunk_));
-
- EmitBranch(instr, true_cond);
-}
-
-
Condition LCodeGen::EmitIsString(Register input,
Register temp1,
Label* is_not_string,
// true and false label should be made, to optimize fallthrough.
Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input);
- // Emits optimized code for %_IsObject(x). Preserves input register.
- // Returns the condition on which a final split to
- // true and false label should be made, to optimize fallthrough.
- Condition EmitIsObject(Register input,
- Label* is_not_object,
- Label* is_object);
-
// Emits optimized code for %_IsString(x). Preserves input register.
// Returns the condition on which a final split to
// true and false label should be made, to optimize fallthrough.
}
-void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
- stream->Add("if is_object(");
- value()->PrintTo(stream);
- stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
-}
-
-
void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if is_string(");
value()->PrintTo(stream);
}
-LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
- DCHECK(instr->value()->representation().IsTagged());
- return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()));
-}
-
-
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
DCHECK(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsConstructCallAndBranch) \
- V(IsObjectAndBranch) \
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
};
-class LIsObjectAndBranch final : public LControlInstruction<1, 0> {
- public:
- explicit LIsObjectAndBranch(LOperand* value) {
- inputs_[0] = value;
- }
-
- LOperand* value() { return inputs_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
- DECLARE_HYDROGEN_ACCESSOR(IsObjectAndBranch)
-
- void PrintDataTo(StringStream* stream) override;
-};
-
-
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
public:
explicit LIsStringAndBranch(LOperand* value, LOperand* temp) {
}
-Condition LCodeGen::EmitIsObject(Register input,
- Register temp1,
- Label* is_not_object,
- Label* is_object) {
- __ JumpIfSmi(input, is_not_object);
-
- __ cmp(input, isolate()->factory()->null_value());
- __ j(equal, is_object);
-
- __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset));
- // Undetectable objects behave like undefined.
- __ test_b(FieldOperand(temp1, Map::kBitFieldOffset),
- 1 << Map::kIsUndetectable);
- __ j(not_zero, is_not_object);
-
- __ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset));
- __ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
- __ j(below, is_not_object);
- __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
- return below_equal;
-}
-
-
-void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
- Register reg = ToRegister(instr->value());
- Register temp = ToRegister(instr->temp());
-
- Condition true_cond = EmitIsObject(
- reg, temp, instr->FalseLabel(chunk_), instr->TrueLabel(chunk_));
-
- EmitBranch(instr, true_cond);
-}
-
-
Condition LCodeGen::EmitIsString(Register input,
Register temp1,
Label* is_not_string,
// true and false label should be made, to optimize fallthrough.
Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input);
- // Emits optimized code for %_IsObject(x). Preserves input register.
- // Returns the condition on which a final split to
- // true and false label should be made, to optimize fallthrough.
- Condition EmitIsObject(Register input,
- Register temp1,
- Label* is_not_object,
- Label* is_object);
-
// Emits optimized code for %_IsString(x). Preserves input register.
// Returns the condition on which a final split to
// true and false label should be made, to optimize fallthrough.
}
-void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
- stream->Add("if is_object(");
- value()->PrintTo(stream);
- stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
-}
-
-
void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if is_string(");
value()->PrintTo(stream);
}
-LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
- DCHECK(instr->value()->representation().IsSmiOrTagged());
- LOperand* temp = TempRegister();
- return new(zone()) LIsObjectAndBranch(UseRegister(instr->value()), temp);
-}
-
-
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
DCHECK(instr->value()->representation().IsTagged());
LOperand* temp = TempRegister();
V(Integer32ToDouble) \
V(InvokeFunction) \
V(IsConstructCallAndBranch) \
- V(IsObjectAndBranch) \
V(IsStringAndBranch) \
V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \
};
-class LIsObjectAndBranch final : public LControlInstruction<1, 1> {
- public:
- LIsObjectAndBranch(LOperand* value, LOperand* temp) {
- inputs_[0] = value;
- temps_[0] = temp;
- }
-
- LOperand* value() { return inputs_[0]; }
- LOperand* temp() { return temps_[0]; }
-
- DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
-
- void PrintDataTo(StringStream* stream) override;
-};
-
-
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
public:
LIsStringAndBranch(LOperand* value, LOperand* temp) {
}
-TEST(IsObject) {
- FunctionTester T("(function(a) { return %_IsObject(a); })", flags);
-
- T.CheckFalse(T.NewObject("(function() {})"));
- T.CheckTrue(T.NewObject("([1])"));
- T.CheckTrue(T.NewObject("({})"));
- T.CheckTrue(T.NewObject("(/x/)"));
- T.CheckFalse(T.undefined());
- T.CheckTrue(T.null());
- T.CheckFalse(T.Val("x"));
- T.CheckFalse(T.Val(1));
-}
-
-
TEST(IsRegExp) {
FunctionTester T("(function(a) { return %_IsRegExp(a); })", flags);
TEST(RuntimeCallInline) {
FLAG_allow_natives_syntax = true;
- FunctionTester T("(function(a) { return %_IsObject(a); })");
+ FunctionTester T("(function(a) { return %_IsSpecObject(a); })");
T.CheckCall(T.false_value(), T.Val(23), T.undefined());
T.CheckCall(T.false_value(), T.Val(4.2), T.undefined());
assertEquals("function", typeof function() {});
assertEquals("object", typeof null);
assertEquals("object", typeof {});
-
- assertTrue(%_IsObject({}));
- assertTrue(%_IsObject(null));
- assertTrue(%_IsObject(/regex/));
- assertFalse(%_IsObject(0));
- assertFalse(%_IsObject(""));
+ assertEquals("object", typeof /regex/);
assertTrue(%_IsSmi(1));
assertFalse(%_IsSmi(1.1));