Revision: 5087
Author: [email protected]
Date: Fri Jul 16 04:21:08 2010
Log: 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
http://code.google.com/p/v8/source/detail?r=5087
Modified:
/branches/bleeding_edge/src/arm/codegen-arm.cc
/branches/bleeding_edge/src/arm/codegen-arm.h
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/codegen.h
/branches/bleeding_edge/src/full-codegen.cc
/branches/bleeding_edge/src/full-codegen.h
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
/branches/bleeding_edge/src/ia32/codegen-ia32.h
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/macros.py
/branches/bleeding_edge/src/mips/codegen-mips.cc
/branches/bleeding_edge/src/mips/codegen-mips.h
/branches/bleeding_edge/src/runtime.js
/branches/bleeding_edge/src/v8natives.js
/branches/bleeding_edge/src/x64/codegen-x64.cc
/branches/bleeding_edge/src/x64/codegen-x64.h
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc Tue Jul 13 13:54:06 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc Fri Jul 16 04:21:08 2010
@@ -4758,6 +4758,24 @@
__ cmp(possible_object, Operand(LAST_JS_OBJECT_TYPE));
cc_reg_ = le;
}
+
+
+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) {
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.h Thu Jul 1 08:06:24 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.h Fri Jul 16 04:21:08 2010
@@ -475,6 +475,7 @@
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);
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Tue Jul 13 13:54:06
2010
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Jul 16 04:21:08
2010
@@ -1906,6 +1906,25 @@
Apply(context_, if_true, if_false);
}
+
+
+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) {
=======================================
--- /branches/bleeding_edge/src/codegen.h Tue Jul 13 13:54:06 2010
+++ /branches/bleeding_edge/src/codegen.h Fri Jul 16 04:21:08 2010
@@ -120,6 +120,7 @@
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 @@
CodeGenerator* previous_;
};
-
#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
// State of used registers in a virtual frame.
=======================================
--- /branches/bleeding_edge/src/full-codegen.cc Thu Jun 10 02:02:16 2010
+++ /branches/bleeding_edge/src/full-codegen.cc Fri Jul 16 04:21:08 2010
@@ -857,6 +857,8 @@
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) {
=======================================
--- /branches/bleeding_edge/src/full-codegen.h Thu Jun 10 02:02:16 2010
+++ /branches/bleeding_edge/src/full-codegen.h Fri Jul 16 04:21:08 2010
@@ -402,6 +402,7 @@
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);
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Thu Jul 15 07:31:49
2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Jul 16 04:21:08
2010
@@ -6435,6 +6435,27 @@
map.Unuse();
destination()->Split(below_equal);
}
+
+
+ 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) {
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.h Thu Jul 15 03:34:08 2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.h Fri Jul 16 04:21:08 2010
@@ -632,6 +632,7 @@
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);
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Thu Jul 8
06:16:51 2010
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Fri Jul 16
04:21:08 2010
@@ -1983,6 +1983,26 @@
Apply(context_, if_true, if_false);
}
+
+
+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) {
=======================================
--- /branches/bleeding_edge/src/macros.py Tue Jul 6 05:57:46 2010
+++ /branches/bleeding_edge/src/macros.py Fri Jul 16 04:21:08 2010
@@ -115,7 +115,8 @@
# 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));
=======================================
--- /branches/bleeding_edge/src/mips/codegen-mips.cc Mon May 17 08:41:35
2010
+++ /branches/bleeding_edge/src/mips/codegen-mips.cc Fri Jul 16 04:21:08
2010
@@ -905,6 +905,11 @@
void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
UNIMPLEMENTED_MIPS();
}
+
+
+void CodeGenerator::GenerateIsSpecObject(ZoneList<Expression*>* args) {
+ UNIMPLEMENTED_MIPS();
+}
void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
=======================================
--- /branches/bleeding_edge/src/mips/codegen-mips.h Wed Apr 7 01:18:51 2010
+++ /branches/bleeding_edge/src/mips/codegen-mips.h Fri Jul 16 04:21:08 2010
@@ -355,6 +355,7 @@
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);
=======================================
--- /branches/bleeding_edge/src/runtime.js Mon Jul 12 08:29:25 2010
+++ /branches/bleeding_edge/src/runtime.js Fri Jul 16 04:21:08 2010
@@ -80,7 +80,7 @@
} 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 @@
// 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 @@
}
// 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 @@
// 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 @@
// 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);
}
=======================================
--- /branches/bleeding_edge/src/v8natives.js Thu Jul 15 00:51:14 2010
+++ /branches/bleeding_edge/src/v8natives.js Fri Jul 16 04:21:08 2010
@@ -225,16 +225,14 @@
// 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 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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);
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc Fri Jul 16 01:20:39 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc Fri Jul 16 04:21:08 2010
@@ -5721,6 +5721,25 @@
obj.Unuse();
destination()->Split(below_equal);
}
+
+
+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) {
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.h Thu Jul 15 03:34:08 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.h Fri Jul 16 04:21:08 2010
@@ -589,6 +589,7 @@
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);
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Thu Jul 8 06:16:51
2010
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Fri Jul 16 04:21:08
2010
@@ -1989,6 +1989,25 @@
Apply(context_, if_true, if_false);
}
+
+
+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) {
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev