Refactor type checks in v8natives.js and runtime.js.
This includes adding a new inline IsSpecObject method to the code generator. The old approach was somehow ineffecient since we would call both IsObject, IsUndetectable and IsFunction to determine if something was an object according to the spec. This change introduces a new macro that determines if something is an object according to the spec (and this does not include null). This change also corrects a few places where undetectable objects was not allowed even when they should be (priorly they would use only IS_SPEC_OBJECT_OR_NULL, which would return false on an undetectable object, the new IS_SPEC_OBJECT returns true on an undetectable object. Review URL: http://codereview.chromium.org/2877018 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5087 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
931bf1d63d
commit
4957326521
@ -4760,6 +4760,24 @@ void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
|
||||
}
|
||||
|
||||
|
||||
void CodeGenerator::GenerateIsSpecObject(ZoneList<Expression*>* args) {
|
||||
// This generates a fast version of:
|
||||
// (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp' ||
|
||||
// typeof(arg) == function).
|
||||
// It includes undetectable objects (as opposed to IsObject).
|
||||
ASSERT(args->length() == 1);
|
||||
Load(args->at(0));
|
||||
Register value = frame_->PopToRegister();
|
||||
__ tst(value, Operand(kSmiTagMask));
|
||||
false_target()->Branch(eq);
|
||||
// Check that this is an object.
|
||||
__ ldr(value, FieldMemOperand(value, HeapObject::kMapOffset));
|
||||
__ ldrb(value, FieldMemOperand(value, Map::kInstanceTypeOffset));
|
||||
__ cmp(value, Operand(FIRST_JS_OBJECT_TYPE));
|
||||
cc_reg_ = ge;
|
||||
}
|
||||
|
||||
|
||||
void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
|
||||
// This generates a fast version of:
|
||||
// (%_ClassOf(arg) === 'Function')
|
||||
|
@ -475,6 +475,7 @@ class CodeGenerator: public AstVisitor {
|
||||
void GenerateIsArray(ZoneList<Expression*>* args);
|
||||
void GenerateIsRegExp(ZoneList<Expression*>* args);
|
||||
void GenerateIsObject(ZoneList<Expression*>* args);
|
||||
void GenerateIsSpecObject(ZoneList<Expression*>* args);
|
||||
void GenerateIsFunction(ZoneList<Expression*>* args);
|
||||
void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
|
||||
|
||||
|
@ -1908,6 +1908,25 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
|
||||
ASSERT(args->length() == 1);
|
||||
|
||||
VisitForValue(args->at(0), kAccumulator);
|
||||
|
||||
Label materialize_true, materialize_false;
|
||||
Label* if_true = NULL;
|
||||
Label* if_false = NULL;
|
||||
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
||||
|
||||
__ BranchOnSmi(r0, if_false);
|
||||
__ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
|
||||
__ b(ge, if_true);
|
||||
__ b(if_false);
|
||||
|
||||
Apply(context_, if_true, if_false);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
||||
ASSERT(args->length() == 1);
|
||||
|
||||
|
@ -120,6 +120,7 @@ namespace internal {
|
||||
F(IsObject, 1, 1) \
|
||||
F(IsFunction, 1, 1) \
|
||||
F(IsUndetectableObject, 1, 1) \
|
||||
F(IsSpecObject, 1, 1) \
|
||||
F(StringAdd, 2, 1) \
|
||||
F(SubString, 3, 1) \
|
||||
F(StringCompare, 2, 1) \
|
||||
@ -180,7 +181,6 @@ class CodeGeneratorScope BASE_EMBEDDED {
|
||||
CodeGenerator* previous_;
|
||||
};
|
||||
|
||||
|
||||
#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
|
||||
|
||||
// State of used registers in a virtual frame.
|
||||
|
@ -857,6 +857,8 @@ void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
|
||||
EmitIsNonNegativeSmi(expr->arguments());
|
||||
} else if (strcmp("_IsObject", *name->ToCString()) == 0) {
|
||||
EmitIsObject(expr->arguments());
|
||||
} else if (strcmp("_IsSpecObject", *name->ToCString()) == 0) {
|
||||
EmitIsSpecObject(expr->arguments());
|
||||
} else if (strcmp("_IsUndetectableObject", *name->ToCString()) == 0) {
|
||||
EmitIsUndetectableObject(expr->arguments());
|
||||
} else if (strcmp("_IsFunction", *name->ToCString()) == 0) {
|
||||
|
@ -402,6 +402,7 @@ class FullCodeGenerator: public AstVisitor {
|
||||
void EmitIsSmi(ZoneList<Expression*>* arguments);
|
||||
void EmitIsNonNegativeSmi(ZoneList<Expression*>* arguments);
|
||||
void EmitIsObject(ZoneList<Expression*>* arguments);
|
||||
void EmitIsSpecObject(ZoneList<Expression*>* arguments);
|
||||
void EmitIsUndetectableObject(ZoneList<Expression*>* arguments);
|
||||
void EmitIsFunction(ZoneList<Expression*>* arguments);
|
||||
void EmitIsArray(ZoneList<Expression*>* arguments);
|
||||
|
@ -6437,6 +6437,27 @@ void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
|
||||
}
|
||||
|
||||
|
||||
void CodeGenerator::GenerateIsSpecObject(ZoneList<Expression*>* args) {
|
||||
// This generates a fast version of:
|
||||
// (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp' ||
|
||||
// typeof(arg) == function).
|
||||
// It includes undetectable objects (as opposed to IsObject).
|
||||
ASSERT(args->length() == 1);
|
||||
Load(args->at(0));
|
||||
Result value = frame_->Pop();
|
||||
value.ToRegister();
|
||||
ASSERT(value.is_valid());
|
||||
__ test(value.reg(), Immediate(kSmiTagMask));
|
||||
destination()->false_target()->Branch(equal);
|
||||
|
||||
// Check that this is an object.
|
||||
frame_->Spill(value.reg());
|
||||
__ CmpObjectType(value.reg(), FIRST_JS_OBJECT_TYPE, value.reg());
|
||||
value.Unuse();
|
||||
destination()->Split(above_equal);
|
||||
}
|
||||
|
||||
|
||||
void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
|
||||
// This generates a fast version of:
|
||||
// (%_ClassOf(arg) === 'Function')
|
||||
|
@ -632,6 +632,7 @@ class CodeGenerator: public AstVisitor {
|
||||
void GenerateIsArray(ZoneList<Expression*>* args);
|
||||
void GenerateIsRegExp(ZoneList<Expression*>* args);
|
||||
void GenerateIsObject(ZoneList<Expression*>* args);
|
||||
void GenerateIsSpecObject(ZoneList<Expression*>* args);
|
||||
void GenerateIsFunction(ZoneList<Expression*>* args);
|
||||
void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
|
||||
|
||||
|
@ -1985,6 +1985,26 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
|
||||
ASSERT(args->length() == 1);
|
||||
|
||||
VisitForValue(args->at(0), kAccumulator);
|
||||
|
||||
Label materialize_true, materialize_false;
|
||||
Label* if_true = NULL;
|
||||
Label* if_false = NULL;
|
||||
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
||||
|
||||
__ test(eax, Immediate(kSmiTagMask));
|
||||
__ j(equal, if_false);
|
||||
__ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ebx);
|
||||
__ j(above_equal, if_true);
|
||||
__ jmp(if_false);
|
||||
|
||||
Apply(context_, if_true, if_false);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
||||
ASSERT(args->length() == 1);
|
||||
|
||||
|
@ -115,7 +115,8 @@ macro FLOOR(arg) = $floor(arg);
|
||||
# Macro for ECMAScript 5 queries of the type:
|
||||
# "Type(O) is object."
|
||||
# This is the same as being either a function or an object in V8 terminology.
|
||||
macro IS_SPEC_OBJECT_OR_NULL(arg) = (%_IsObject(arg) || %_IsFunction(arg));
|
||||
# In addition, an undetectable object is also included by this.
|
||||
macro IS_SPEC_OBJECT(arg) = (%_IsSpecObject(arg));
|
||||
|
||||
# Inline macros. Use %IS_VAR to make sure arg is evaluated only once.
|
||||
macro NUMBER_IS_NAN(arg) = (!%_IsSmi(%IS_VAR(arg)) && !(arg == arg));
|
||||
|
@ -907,6 +907,11 @@ void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
|
||||
}
|
||||
|
||||
|
||||
void CodeGenerator::GenerateIsSpecObject(ZoneList<Expression*>* args) {
|
||||
UNIMPLEMENTED_MIPS();
|
||||
}
|
||||
|
||||
|
||||
void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
|
||||
UNIMPLEMENTED_MIPS();
|
||||
}
|
||||
|
@ -355,6 +355,7 @@ class CodeGenerator: public AstVisitor {
|
||||
void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
|
||||
|
||||
void GenerateIsObject(ZoneList<Expression*>* args);
|
||||
void GenerateIsSpecObject(ZoneList<Expression*>* args);
|
||||
void GenerateIsFunction(ZoneList<Expression*>* args);
|
||||
void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
|
||||
void GenerateStringAdd(ZoneList<Expression*>* args);
|
||||
|
@ -80,7 +80,7 @@ function EQUALS(y) {
|
||||
} else {
|
||||
// x is not a number, boolean, null or undefined.
|
||||
if (y == null) return 1; // not equal
|
||||
if (IS_SPEC_OBJECT_OR_NULL(y)) {
|
||||
if (IS_SPEC_OBJECT(y)) {
|
||||
return %_ObjectEquals(x, y) ? 0 : 1;
|
||||
}
|
||||
|
||||
@ -345,7 +345,7 @@ function DELETE(key) {
|
||||
|
||||
// ECMA-262, section 11.8.7, page 54.
|
||||
function IN(x) {
|
||||
if (x == null || !IS_SPEC_OBJECT_OR_NULL(x)) {
|
||||
if (!IS_SPEC_OBJECT(x)) {
|
||||
throw %MakeTypeError('invalid_in_operator_use', [this, x]);
|
||||
}
|
||||
return %_IsNonNegativeSmi(this) ? %HasElement(x, this) : %HasProperty(x, %ToString(this));
|
||||
@ -363,13 +363,13 @@ function INSTANCE_OF(F) {
|
||||
}
|
||||
|
||||
// If V is not an object, return false.
|
||||
if (IS_NULL(V) || !IS_SPEC_OBJECT_OR_NULL(V)) {
|
||||
if (!IS_SPEC_OBJECT(V)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the prototype of F; if it is not an object, throw an error.
|
||||
var O = F.prototype;
|
||||
if (IS_NULL(O) || !IS_SPEC_OBJECT_OR_NULL(O)) {
|
||||
if (!IS_SPEC_OBJECT(O)) {
|
||||
throw %MakeTypeError('instanceof_nonobject_proto', [O]);
|
||||
}
|
||||
|
||||
@ -483,8 +483,7 @@ function ToPrimitive(x, hint) {
|
||||
// Fast case check.
|
||||
if (IS_STRING(x)) return x;
|
||||
// Normal behavior.
|
||||
if (!IS_SPEC_OBJECT_OR_NULL(x)) return x;
|
||||
if (x == null) return x; // check for null, undefined
|
||||
if (!IS_SPEC_OBJECT(x)) return x;
|
||||
if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
|
||||
return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x);
|
||||
}
|
||||
@ -583,13 +582,10 @@ function SameValue(x, y) {
|
||||
// Returns if the given x is a primitive value - not an object or a
|
||||
// function.
|
||||
function IsPrimitive(x) {
|
||||
if (!IS_SPEC_OBJECT_OR_NULL(x)) {
|
||||
return true;
|
||||
} else {
|
||||
// Even though the type of null is "object", null is still
|
||||
// considered a primitive value.
|
||||
return IS_NULL(x);
|
||||
}
|
||||
// Even though the type of null is "object", null is still
|
||||
// considered a primitive value. IS_SPEC_OBJECT handles this correctly
|
||||
// (i.e., it will return false if x is null).
|
||||
return !IS_SPEC_OBJECT(x);
|
||||
}
|
||||
|
||||
|
||||
|
@ -225,16 +225,14 @@ function ObjectHasOwnProperty(V) {
|
||||
|
||||
// ECMA-262 - 15.2.4.6
|
||||
function ObjectIsPrototypeOf(V) {
|
||||
if (!IS_SPEC_OBJECT_OR_NULL(V) && !IS_UNDETECTABLE(V)) return false;
|
||||
if (!IS_SPEC_OBJECT(V)) return false;
|
||||
return %IsInPrototypeChain(this, V);
|
||||
}
|
||||
|
||||
|
||||
// ECMA-262 - 15.2.4.6
|
||||
function ObjectPropertyIsEnumerable(V) {
|
||||
if (this == null) return false;
|
||||
if (!IS_SPEC_OBJECT_OR_NULL(this)) return false;
|
||||
return %IsPropertyEnumerable(this, ToString(V));
|
||||
return %IsPropertyEnumerable(ToObject(this), ToString(V));
|
||||
}
|
||||
|
||||
|
||||
@ -279,8 +277,7 @@ function ObjectLookupSetter(name) {
|
||||
|
||||
|
||||
function ObjectKeys(obj) {
|
||||
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
|
||||
!IS_UNDETECTABLE(obj))
|
||||
if (!IS_SPEC_OBJECT(obj))
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["keys"]);
|
||||
return %LocalKeys(obj);
|
||||
}
|
||||
@ -329,7 +326,7 @@ function FromPropertyDescriptor(desc) {
|
||||
|
||||
// ES5 8.10.5.
|
||||
function ToPropertyDescriptor(obj) {
|
||||
if (!IS_SPEC_OBJECT_OR_NULL(obj)) {
|
||||
if (!IS_SPEC_OBJECT(obj)) {
|
||||
throw MakeTypeError("property_desc_object", [obj]);
|
||||
}
|
||||
var desc = new PropertyDescriptor();
|
||||
@ -626,8 +623,7 @@ function DefineOwnProperty(obj, p, desc, should_throw) {
|
||||
|
||||
// ES5 section 15.2.3.2.
|
||||
function ObjectGetPrototypeOf(obj) {
|
||||
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
|
||||
!IS_UNDETECTABLE(obj))
|
||||
if (!IS_SPEC_OBJECT(obj))
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["getPrototypeOf"]);
|
||||
return obj.__proto__;
|
||||
}
|
||||
@ -635,8 +631,7 @@ function ObjectGetPrototypeOf(obj) {
|
||||
|
||||
// ES5 section 15.2.3.3
|
||||
function ObjectGetOwnPropertyDescriptor(obj, p) {
|
||||
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
|
||||
!IS_UNDETECTABLE(obj))
|
||||
if (!IS_SPEC_OBJECT(obj))
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyDescriptor"]);
|
||||
var desc = GetOwnProperty(obj, p);
|
||||
return FromPropertyDescriptor(desc);
|
||||
@ -645,8 +640,7 @@ function ObjectGetOwnPropertyDescriptor(obj, p) {
|
||||
|
||||
// ES5 section 15.2.3.4.
|
||||
function ObjectGetOwnPropertyNames(obj) {
|
||||
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
|
||||
!IS_UNDETECTABLE(obj))
|
||||
if (!IS_SPEC_OBJECT(obj))
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyNames"]);
|
||||
|
||||
// Find all the indexed properties.
|
||||
@ -698,7 +692,7 @@ function ObjectGetOwnPropertyNames(obj) {
|
||||
|
||||
// ES5 section 15.2.3.5.
|
||||
function ObjectCreate(proto, properties) {
|
||||
if (!IS_SPEC_OBJECT_OR_NULL(proto)) {
|
||||
if (!IS_SPEC_OBJECT(proto) && proto !== null) {
|
||||
throw MakeTypeError("proto_object_or_null", [proto]);
|
||||
}
|
||||
var obj = new $Object();
|
||||
@ -710,8 +704,7 @@ function ObjectCreate(proto, properties) {
|
||||
|
||||
// ES5 section 15.2.3.6.
|
||||
function ObjectDefineProperty(obj, p, attributes) {
|
||||
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
|
||||
!IS_UNDETECTABLE(obj)) {
|
||||
if (!IS_SPEC_OBJECT(obj)) {
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["defineProperty"]);
|
||||
}
|
||||
var name = ToString(p);
|
||||
@ -723,8 +716,7 @@ function ObjectDefineProperty(obj, p, attributes) {
|
||||
|
||||
// ES5 section 15.2.3.7.
|
||||
function ObjectDefineProperties(obj, properties) {
|
||||
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
|
||||
!IS_UNDETECTABLE(obj))
|
||||
if (!IS_SPEC_OBJECT(obj))
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["defineProperties"]);
|
||||
var props = ToObject(properties);
|
||||
var key_values = [];
|
||||
@ -747,8 +739,7 @@ function ObjectDefineProperties(obj, properties) {
|
||||
|
||||
// ES5 section 15.2.3.8.
|
||||
function ObjectSeal(obj) {
|
||||
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
|
||||
!IS_UNDETECTABLE(obj)) {
|
||||
if (!IS_SPEC_OBJECT(obj)) {
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["seal"]);
|
||||
}
|
||||
var names = ObjectGetOwnPropertyNames(obj);
|
||||
@ -764,8 +755,7 @@ function ObjectSeal(obj) {
|
||||
|
||||
// ES5 section 15.2.3.9.
|
||||
function ObjectFreeze(obj) {
|
||||
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
|
||||
!IS_UNDETECTABLE(obj)) {
|
||||
if (!IS_SPEC_OBJECT(obj)) {
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["freeze"]);
|
||||
}
|
||||
var names = ObjectGetOwnPropertyNames(obj);
|
||||
@ -782,8 +772,7 @@ function ObjectFreeze(obj) {
|
||||
|
||||
// ES5 section 15.2.3.10
|
||||
function ObjectPreventExtension(obj) {
|
||||
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
|
||||
!IS_UNDETECTABLE(obj)) {
|
||||
if (!IS_SPEC_OBJECT(obj)) {
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["preventExtension"]);
|
||||
}
|
||||
%PreventExtensions(obj);
|
||||
@ -793,8 +782,7 @@ function ObjectPreventExtension(obj) {
|
||||
|
||||
// ES5 section 15.2.3.11
|
||||
function ObjectIsSealed(obj) {
|
||||
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
|
||||
!IS_UNDETECTABLE(obj)) {
|
||||
if (!IS_SPEC_OBJECT(obj)) {
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["isSealed"]);
|
||||
}
|
||||
var names = ObjectGetOwnPropertyNames(obj);
|
||||
@ -812,8 +800,7 @@ function ObjectIsSealed(obj) {
|
||||
|
||||
// ES5 section 15.2.3.12
|
||||
function ObjectIsFrozen(obj) {
|
||||
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
|
||||
!IS_UNDETECTABLE(obj)) {
|
||||
if (!IS_SPEC_OBJECT(obj)) {
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["isFrozen"]);
|
||||
}
|
||||
var names = ObjectGetOwnPropertyNames(obj);
|
||||
@ -832,8 +819,7 @@ function ObjectIsFrozen(obj) {
|
||||
|
||||
// ES5 section 15.2.3.13
|
||||
function ObjectIsExtensible(obj) {
|
||||
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
|
||||
!IS_UNDETECTABLE(obj)) {
|
||||
if (!IS_SPEC_OBJECT(obj)) {
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["preventExtension"]);
|
||||
}
|
||||
return %IsExtensible(obj);
|
||||
|
@ -5723,6 +5723,25 @@ void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
|
||||
}
|
||||
|
||||
|
||||
void CodeGenerator::GenerateIsSpecObject(ZoneList<Expression*>* args) {
|
||||
// This generates a fast version of:
|
||||
// (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp' ||
|
||||
// typeof(arg) == function).
|
||||
// It includes undetectable objects (as opposed to IsObject).
|
||||
ASSERT(args->length() == 1);
|
||||
Load(args->at(0));
|
||||
Result value = frame_->Pop();
|
||||
value.ToRegister();
|
||||
ASSERT(value.is_valid());
|
||||
Condition is_smi = masm_->CheckSmi(value.reg());
|
||||
destination()->false_target()->Branch(is_smi);
|
||||
// Check that this is an object.
|
||||
__ CmpObjectType(value.reg(), FIRST_JS_OBJECT_TYPE, kScratchRegister);
|
||||
value.Unuse();
|
||||
destination()->Split(above_equal);
|
||||
}
|
||||
|
||||
|
||||
void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
|
||||
// This generates a fast version of:
|
||||
// (%_ClassOf(arg) === 'Function')
|
||||
|
@ -589,6 +589,7 @@ class CodeGenerator: public AstVisitor {
|
||||
void GenerateIsArray(ZoneList<Expression*>* args);
|
||||
void GenerateIsRegExp(ZoneList<Expression*>* args);
|
||||
void GenerateIsObject(ZoneList<Expression*>* args);
|
||||
void GenerateIsSpecObject(ZoneList<Expression*>* args);
|
||||
void GenerateIsFunction(ZoneList<Expression*>* args);
|
||||
void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
|
||||
|
||||
|
@ -1991,6 +1991,25 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
|
||||
ASSERT(args->length() == 1);
|
||||
|
||||
VisitForValue(args->at(0), kAccumulator);
|
||||
|
||||
Label materialize_true, materialize_false;
|
||||
Label* if_true = NULL;
|
||||
Label* if_false = NULL;
|
||||
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
||||
|
||||
__ JumpIfSmi(rax, if_false);
|
||||
__ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx);
|
||||
__ j(above_equal, if_true);
|
||||
__ jmp(if_false);
|
||||
|
||||
Apply(context_, if_true, if_false);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
|
||||
ASSERT(args->length() == 1);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user