Revision: 3651
Author: [email protected]
Date: Tue Jan 19 06:15:47 2010
Log: Fix some usage of "this" in builtins
The implementation of Object.prototype.valueOf and
Object.prototype.toString now calls ToObject on "this" as mandated by the
spec.
Review URL: http://codereview.chromium.org/542112
http://code.google.com/p/v8/source/detail?r=3651
Modified:
/branches/bleeding_edge/src/arm/codegen-arm.cc
/branches/bleeding_edge/src/arm/codegen-arm.h
/branches/bleeding_edge/src/codegen.cc
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
/branches/bleeding_edge/src/ia32/codegen-ia32.h
/branches/bleeding_edge/src/macros.py
/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/test/mjsunit/value-wrapper.js
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc Mon Jan 18 00:36:06 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc Tue Jan 19 06:15:47 2010
@@ -3468,6 +3468,20 @@
__ CompareObjectType(r0, map_reg, r1, JS_FUNCTION_TYPE);
cc_reg_ = eq;
}
+
+
+void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>*
args) {
+ VirtualFrame::SpilledScope spilled_scope;
+ ASSERT(args->length() == 1);
+ LoadAndSpill(args->at(0));
+ frame_->EmitPop(r0);
+ __ tst(r0, Operand(kSmiTagMask));
+ false_target()->Branch(eq);
+ __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
+ __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
+ __ tst(r1, Operand(1 << Map::kIsUndetectable));
+ cc_reg_ = ne;
+}
void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.h Fri Jan 15 05:42:32 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.h Tue Jan 19 06:15:47 2010
@@ -341,6 +341,7 @@
void GenerateIsArray(ZoneList<Expression*>* args);
void GenerateIsObject(ZoneList<Expression*>* args);
void GenerateIsFunction(ZoneList<Expression*>* args);
+ void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
// Support for construct call checks.
void GenerateIsConstructCall(ZoneList<Expression*>* args);
=======================================
--- /branches/bleeding_edge/src/codegen.cc Fri Jan 8 03:58:15 2010
+++ /branches/bleeding_edge/src/codegen.cc Tue Jan 19 06:15:47 2010
@@ -344,6 +344,7 @@
{&CodeGenerator::GenerateRandomPositiveSmi, "_RandomPositiveSmi"},
{&CodeGenerator::GenerateIsObject, "_IsObject"},
{&CodeGenerator::GenerateIsFunction, "_IsFunction"},
+ {&CodeGenerator::GenerateIsUndetectableObject, "_IsUndetectableObject"},
{&CodeGenerator::GenerateStringAdd, "_StringAdd"},
{&CodeGenerator::GenerateSubString, "_SubString"},
{&CodeGenerator::GenerateStringCompare, "_StringCompare"},
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Jan 15 05:42:32
2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue Jan 19 06:15:47
2010
@@ -5181,6 +5181,26 @@
temp.Unuse();
destination()->Split(equal);
}
+
+
+void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>*
args) {
+ ASSERT(args->length() == 1);
+ Load(args->at(0));
+ Result obj = frame_->Pop();
+ obj.ToRegister();
+ __ test(obj.reg(), Immediate(kSmiTagMask));
+ destination()->false_target()->Branch(zero);
+ Result temp = allocator()->Allocate();
+ ASSERT(temp.is_valid());
+ __ mov(temp.reg(),
+ FieldOperand(obj.reg(), HeapObject::kMapOffset));
+ __ movzx_b(temp.reg(),
+ FieldOperand(temp.reg(), Map::kBitFieldOffset));
+ __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable));
+ obj.Unuse();
+ temp.Unuse();
+ destination()->Split(not_zero);
+}
void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.h Fri Jan 15 05:42:32 2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.h Tue Jan 19 06:15:47 2010
@@ -517,6 +517,7 @@
void GenerateIsArray(ZoneList<Expression*>* args);
void GenerateIsObject(ZoneList<Expression*>* args);
void GenerateIsFunction(ZoneList<Expression*>* args);
+ void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
// Support for construct call checks.
void GenerateIsConstructCall(ZoneList<Expression*>* args);
=======================================
--- /branches/bleeding_edge/src/macros.py Thu Jan 7 23:49:07 2010
+++ /branches/bleeding_edge/src/macros.py Tue Jan 19 06:15:47 2010
@@ -92,6 +92,7 @@
macro IS_SCRIPT(arg) = (%_ClassOf(arg) === 'Script');
macro IS_ARGUMENTS(arg) = (%_ClassOf(arg) === 'Arguments');
macro IS_GLOBAL(arg) = (%_ClassOf(arg) === 'global');
+macro IS_UNDETECTABLE(arg) = (%_IsUndetectableObject(arg));
macro FLOOR(arg) = $floor(arg);
# Inline macros. Use %IS_VAR to make sure arg is evaluated only once.
=======================================
--- /branches/bleeding_edge/src/runtime.js Wed Jan 13 05:26:31 2010
+++ /branches/bleeding_edge/src/runtime.js Tue Jan 19 06:15:47 2010
@@ -541,7 +541,9 @@
if (IS_STRING(x)) return new $String(x);
if (IS_NUMBER(x)) return new $Number(x);
if (IS_BOOLEAN(x)) return new $Boolean(x);
- if (x == null) throw %MakeTypeError('null_to_object', []);
+ if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) {
+ throw %MakeTypeError('null_to_object', []);
+ }
return x;
}
=======================================
--- /branches/bleeding_edge/src/v8natives.js Fri Jan 15 07:34:32 2010
+++ /branches/bleeding_edge/src/v8natives.js Tue Jan 19 06:15:47 2010
@@ -197,7 +197,7 @@
// ECMA-262 - 15.2.4.2
function ObjectToString() {
- return "[object " + %_ClassOf(this) + "]";
+ return "[object " + %_ClassOf(ToObject(this)) + "]";
}
@@ -209,7 +209,7 @@
// ECMA-262 - 15.2.4.4
function ObjectValueOf() {
- return this;
+ return ToObject(this);
}
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc Mon Jan 18 03:22:03 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc Tue Jan 19 06:15:47 2010
@@ -3620,6 +3620,22 @@
obj.Unuse();
destination()->Split(equal);
}
+
+
+void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>*
args) {
+ ASSERT(args->length() == 1);
+ Load(args->at(0));
+ Result obj = frame_->Pop();
+ obj.ToRegister();
+ Condition is_smi = masm_->CheckSmi(obj.reg());
+ destination()->false_target()->Branch(is_smi);
+ __ movq(kScratchRegister, FieldOperand(obj.reg(),
HeapObject::kMapOffset));
+ __ movzxbl(kScratchRegister,
+ FieldOperand(kScratchRegister, Map::kBitFieldOffset));
+ __ testl(kScratchRegister, Immediate(1 << Map::kIsUndetectable));
+ obj.Unuse();
+ destination()->Split(not_zero);
+}
void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.h Mon Jan 18 03:22:03 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.h Tue Jan 19 06:15:47 2010
@@ -514,6 +514,7 @@
void GenerateIsArray(ZoneList<Expression*>* args);
void GenerateIsObject(ZoneList<Expression*>* args);
void GenerateIsFunction(ZoneList<Expression*>* args);
+ void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
// Support for construct call checks.
void GenerateIsConstructCall(ZoneList<Expression*>* args);
=======================================
--- /branches/bleeding_edge/test/mjsunit/value-wrapper.js Fri Jan 15
05:42:32 2010
+++ /branches/bleeding_edge/test/mjsunit/value-wrapper.js Tue Jan 19
06:15:47 2010
@@ -28,6 +28,9 @@
// When calling user-defined functions on strings, booleans or
// numbers, we should create a wrapper object.
+// When running the tests use loops to ensure that the call site moves
through
+// the different IC states and that both the runtime system and the
generated
+// IC code is tested.
function RunTests() {
for (var i = 0; i < 10; i++) {
assertEquals('object', 'xxx'.TypeOfThis());
@@ -77,6 +80,22 @@
assertEquals('object', (42)[7]());
assertEquals('object', (3.14)[7]());
}
+
+ for (var i = 0; i < 10; i++) {
+ assertEquals('object', typeof 'xxx'.ObjectValueOf());
+ assertEquals('object', typeof true.ObjectValueOf());
+ assertEquals('object', typeof false.ObjectValueOf());
+ assertEquals('object', typeof (42).ObjectValueOf());
+ assertEquals('object', typeof (3.14).ObjectValueOf());
+ }
+
+ for (var i = 0; i < 10; i++) {
+ assertEquals('[object String]', 'xxx'.ObjectToString());
+ assertEquals('[object Boolean]', true.ObjectToString());
+ assertEquals('[object Boolean]', false.ObjectToString());
+ assertEquals('[object Number]', (42).ObjectToString());
+ assertEquals('[object Number]', (3.14).ObjectToString());
+ }
}
function TypeOfThis() { return typeof this; }
@@ -87,7 +106,14 @@
Number.prototype.TypeOfThis = TypeOfThis;
Boolean.prototype[7] = TypeOfThis;
Number.prototype[7] = TypeOfThis;
-
+
+String.prototype.ObjectValueOf = Object.prototype.valueOf;
+Boolean.prototype.ObjectValueOf = Object.prototype.valueOf;
+Number.prototype.ObjectValueOf = Object.prototype.valueOf;
+
+String.prototype.ObjectToString = Object.prototype.toString;
+Boolean.prototype.ObjectToString = Object.prototype.toString;
+Number.prototype.ObjectToString = Object.prototype.toString;
RunTests();
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev