}
+void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) {
+ VirtualFrame::SpilledScope spilled_scope;
+ ASSERT(args->length() == 1);
+ LoadAndSpill(args->at(0)); // Load the object.
+ frame_->CallRuntime(Runtime::kClassOf, 1);
+ frame_->EmitPush(r0);
+}
+
+
void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope;
ASSERT(args->length() == 1);
void GenerateArgumentsLength(ZoneList<Expression*>* args);
void GenerateArgumentsAccess(ZoneList<Expression*>* args);
- // Support for accessing the value field of an object (used by Date).
+ // Support for accessing the class and value fields of an object.
+ void GenerateClassOf(ZoneList<Expression*>* args);
void GenerateValueOf(ZoneList<Expression*>* args);
void GenerateSetValueOf(ZoneList<Expression*>* args);
{&CodeGenerator::GenerateIsConstructCall, "_IsConstructCall"},
{&CodeGenerator::GenerateArgumentsLength, "_ArgumentsLength"},
{&CodeGenerator::GenerateArgumentsAccess, "_Arguments"},
+ {&CodeGenerator::GenerateClassOf, "_ClassOf"},
{&CodeGenerator::GenerateValueOf, "_ValueOf"},
{&CodeGenerator::GenerateSetValueOf, "_SetValueOf"},
{&CodeGenerator::GenerateFastCharCodeAt, "_FastCharCodeAt"},
}
+void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) {
+ ASSERT(args->length() == 1);
+ JumpTarget leave, null, function, non_function_constructor;
+ Load(args->at(0)); // Load the object.
+ Result obj = frame_->Pop();
+ obj.ToRegister();
+ frame_->Spill(obj.reg());
+
+ // If the object is a smi, we return null.
+ __ test(obj.reg(), Immediate(kSmiTagMask));
+ null.Branch(zero);
+
+ // Check that the object is a JS object but take special care of JS
+ // functions to make sure they have 'Function' as their class.
+ { Result tmp = allocator()->Allocate();
+ __ mov(obj.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset));
+ __ movzx_b(tmp.reg(), FieldOperand(obj.reg(), Map::kInstanceTypeOffset));
+ __ cmp(tmp.reg(), FIRST_JS_OBJECT_TYPE);
+ null.Branch(less);
+
+ // As long as JS_FUNCTION_TYPE is the last instance type and it is
+ // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
+ // LAST_JS_OBJECT_TYPE.
+ ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
+ ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
+ __ cmp(tmp.reg(), JS_FUNCTION_TYPE);
+ function.Branch(equal);
+ }
+
+ // Check if the constructor in the map is a function.
+ { Result tmp = allocator()->Allocate();
+ __ mov(obj.reg(), FieldOperand(obj.reg(), Map::kConstructorOffset));
+ __ CmpObjectType(obj.reg(), JS_FUNCTION_TYPE, tmp.reg());
+ non_function_constructor.Branch(not_equal);
+ }
+
+ // The map register now contains the constructor function. Grab the
+ // instance class name from there.
+ __ mov(obj.reg(),
+ FieldOperand(obj.reg(), JSFunction::kSharedFunctionInfoOffset));
+ __ mov(obj.reg(),
+ FieldOperand(obj.reg(), SharedFunctionInfo::kInstanceClassNameOffset));
+ frame_->Push(&obj);
+ leave.Jump();
+
+ // Functions have class 'Function'.
+ function.Bind();
+ frame_->Push(Factory::function_class_symbol());
+ leave.Jump();
+
+ // Objects with a non-function constructor have class 'Object'.
+ non_function_constructor.Bind();
+ frame_->Push(Factory::Object_symbol());
+ leave.Jump();
+
+ // Non-JS objects have class null.
+ null.Bind();
+ frame_->Push(Factory::null_value());
+
+ // All done.
+ leave.Bind();
+}
+
+
void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
JumpTarget leave;
void GenerateArgumentsLength(ZoneList<Expression*>* args);
void GenerateArgumentsAccess(ZoneList<Expression*>* args);
- // Support for accessing the value field of an object (used by Date).
+ // Support for accessing the class and value fields of an object.
+ void GenerateClassOf(ZoneList<Expression*>* args);
void GenerateValueOf(ZoneList<Expression*>* args);
void GenerateSetValueOf(ZoneList<Expression*>* args);
macro IS_STRING(arg) = (typeof(arg) === 'string');
macro IS_OBJECT(arg) = (typeof(arg) === 'object');
macro IS_BOOLEAN(arg) = (typeof(arg) === 'boolean');
-macro IS_REGEXP(arg) = %HasRegExpClass(arg);
-macro IS_ARRAY(arg) = %HasArrayClass(arg);
-macro IS_DATE(arg) = %HasDateClass(arg);
-macro IS_NUMBER_WRAPPER(arg) = %HasNumberClass(arg);
-macro IS_STRING_WRAPPER(arg) = %HasStringClass(arg);
-macro IS_ERROR(arg) = (%ClassOf(arg) === 'Error');
-macro IS_SCRIPT(arg) = (%ClassOf(arg) === 'Script');
+macro IS_ARRAY(arg) = (%_IsArray(arg));
+macro IS_REGEXP(arg) = (%_ClassOf(arg) === 'RegExp');
+macro IS_DATE(arg) = (%_ClassOf(arg) === 'Date');
+macro IS_NUMBER_WRAPPER(arg) = (%_ClassOf(arg) === 'Number');
+macro IS_STRING_WRAPPER(arg) = (%_ClassOf(arg) === 'String');
+macro IS_BOOLEAN_WRAPPER(arg) = (%_ClassOf(arg) === 'Boolean');
+macro IS_ERROR(arg) = (%_ClassOf(arg) === 'Error');
+macro IS_SCRIPT(arg) = (%_ClassOf(arg) === 'Script');
+macro IS_ARGUMENTS(arg) = (%_ClassOf(arg) === 'Arguments');
macro FLOOR(arg) = %Math_floor(arg);
# Inline macros. Use %IS_VAR to make sure arg is evaluated only once.
ObjectMirror.prototype.className = function() {
- return %ClassOf(this.value_);
+ return %_ClassOf(this.value_);
};
}
-static Object* Runtime_HasStringClass(Arguments args) {
- return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::String_symbol()));
-}
-
-
-static Object* Runtime_HasDateClass(Arguments args) {
- return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Date_symbol()));
-}
-
-
-static Object* Runtime_HasArrayClass(Arguments args) {
- return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Array_symbol()));
-}
-
-
-static Object* Runtime_HasFunctionClass(Arguments args) {
- return Heap::ToBoolean(
- args[0]->HasSpecificClassOf(Heap::function_class_symbol()));
-}
-
-
-static Object* Runtime_HasNumberClass(Arguments args) {
- return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Number_symbol()));
-}
-
-
-static Object* Runtime_HasBooleanClass(Arguments args) {
- return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Boolean_symbol()));
-}
-
-
-static Object* Runtime_HasArgumentsClass(Arguments args) {
- return Heap::ToBoolean(
- args[0]->HasSpecificClassOf(Heap::Arguments_symbol()));
-}
-
-
-static Object* Runtime_HasRegExpClass(Arguments args) {
- return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::RegExp_symbol()));
-}
-
-
static Object* Runtime_IsInPrototypeChain(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
F(GetScript, 1) \
\
F(ClassOf, 1) \
- F(HasDateClass, 1) \
- F(HasStringClass, 1) \
- F(HasArrayClass, 1) \
- F(HasFunctionClass, 1) \
- F(HasNumberClass, 1) \
- F(HasBooleanClass, 1) \
- F(HasArgumentsClass, 1) \
- F(HasRegExpClass, 1) \
F(SetCode, 2) \
\
F(CreateApiFunction, 1) \
// First check whether length is a positive Smi and args is an
// array. This is the fast case. If this fails, we do the slow case
// that takes care of more eventualities.
- if (%_IsArray(args)) {
+ if (IS_ARRAY(args)) {
length = args.length;
if (%_IsSmi(length) && length >= 0 && length < 0x800000 && IS_FUNCTION(this)) {
return length;
}
// Make sure the arguments list has the right type.
- if (args != null &&
- !%HasArrayClass(args) &&
- !%HasArgumentsClass(args)) {
+ if (args != null && !IS_ARRAY(args) && !IS_ARGUMENTS(args)) {
throw %MakeTypeError('apply_wrong_args', []);
}
// ECMA-262 section 15.5.4.2
function StringToString() {
- if (!IS_STRING(this) && !%HasStringClass(this))
+ if (!IS_STRING(this) && !IS_STRING_WRAPPER(this))
throw new $TypeError('String.prototype.toString is not generic');
return %_ValueOf(this);
}
// ECMA-262 section 15.5.4.3
function StringValueOf() {
- if (!IS_STRING(this) && !%HasStringClass(this))
+ if (!IS_STRING(this) && !IS_STRING_WRAPPER(this))
throw new $TypeError('String.prototype.valueOf is not generic');
return %_ValueOf(this);
}
// ECMA-262 - 15.2.4.2
function ObjectToString() {
- var c = %ClassOf(this);
+ var c = %_ClassOf(this);
// Hide Arguments from the outside.
if (c === 'Arguments') c = 'Object';
return "[object " + c + "]";
function BooleanToString() {
// NOTE: Both Boolean objects and values can enter here as
// 'this'. This is not as dictated by ECMA-262.
- if (!IS_BOOLEAN(this) && !%HasBooleanClass(this))
+ if (!IS_BOOLEAN(this) && !IS_BOOLEAN_WRAPPER(this))
throw new $TypeError('Boolean.prototype.toString is not generic');
return ToString(%_ValueOf(this));
}
function BooleanValueOf() {
// NOTE: Both Boolean objects and values can enter here as
// 'this'. This is not as dictated by ECMA-262.
- if (!IS_BOOLEAN(this) && !%HasBooleanClass(this))
+ if (!IS_BOOLEAN(this) && !IS_BOOLEAN_WRAPPER(this))
throw new $TypeError('Boolean.prototype.valueOf is not generic');
return %_ValueOf(this);
}
// 'this'. This is not as dictated by ECMA-262.
var number = this;
if (!IS_NUMBER(this)) {
- if (!%HasNumberClass(this))
+ if (!IS_NUMBER_WRAPPER(this))
throw new $TypeError('Number.prototype.toString is not generic');
// Get the value of this number in case it's an object.
number = %_ValueOf(this);
function NumberValueOf() {
// NOTE: Both Number objects and values can enter here as
// 'this'. This is not as dictated by ECMA-262.
- if (!IS_NUMBER(this) && !%HasNumberClass(this))
+ if (!IS_NUMBER(this) && !IS_NUMBER_WRAPPER(this))
throw new $TypeError('Number.prototype.valueOf is not generic');
return %_ValueOf(this);
}
$Function.prototype.constructor = $Function;
function FunctionSourceString(func) {
- // NOTE: Both Function objects and values can enter here as
- // 'func'. This is not as dictated by ECMA-262.
- if (!IS_FUNCTION(func) && !%HasFunctionClass(func))
+ if (!IS_FUNCTION(func)) {
throw new $TypeError('Function.prototype.toString is not generic');
+ }
var source = %FunctionGetSourceCode(func);
if (!IS_STRING(source)) {
}
+void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) {
+ // TODO(X64): Optimize this like it's done on IA-32.
+ ASSERT(args->length() == 1);
+ Load(args->at(0)); // Load the object.
+ Result result = frame_->CallRuntime(Runtime::kClassOf, 1);
+ frame_->Push(&result);
+}
+
+
void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2);
JumpTarget leave;
void GenerateArgumentsLength(ZoneList<Expression*>* args);
void GenerateArgumentsAccess(ZoneList<Expression*>* args);
- // Support for accessing the value field of an object (used by Date).
+ // Support for accessing the class and value fields of an object.
+ void GenerateClassOf(ZoneList<Expression*>* args);
void GenerateValueOf(ZoneList<Expression*>* args);
void GenerateSetValueOf(ZoneList<Expression*>* args);