Commit f0df4a6c authored by mmaly@chromium.org's avatar mmaly@chromium.org

Revert "This is not wrapped for strict mode and builtin functions."

This reverts commit 6845

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6847 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 963472c5
...@@ -2332,9 +2332,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -2332,9 +2332,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
break; break;
case STRING_CHECK: case STRING_CHECK:
if (!function->IsBuiltin() && !function_info->strict_mode()) { if (!function->IsBuiltin()) {
// Calling non-strict non-builtins with a value as the receiver // Calling non-builtins with a value as receiver requires boxing.
// requires boxing.
__ jmp(&miss); __ jmp(&miss);
} else { } else {
// Check that the object is a two-byte string or a symbol. // Check that the object is a two-byte string or a symbol.
...@@ -2349,9 +2348,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -2349,9 +2348,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
break; break;
case NUMBER_CHECK: { case NUMBER_CHECK: {
if (!function->IsBuiltin() && !function_info->strict_mode()) { if (!function->IsBuiltin()) {
// Calling non-strict non-builtins with a value as the receiver // Calling non-builtins with a value as receiver requires boxing.
// requires boxing.
__ jmp(&miss); __ jmp(&miss);
} else { } else {
Label fast; Label fast;
...@@ -2371,9 +2369,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -2371,9 +2369,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
} }
case BOOLEAN_CHECK: { case BOOLEAN_CHECK: {
if (!function->IsBuiltin() && !function_info->strict_mode()) { if (!function->IsBuiltin()) {
// Calling non-strict non-builtins with a value as the receiver // Calling non-builtins with a value as receiver requires boxing.
// requires boxing.
__ jmp(&miss); __ jmp(&miss);
} else { } else {
Label fast; Label fast;
......
...@@ -2204,9 +2204,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -2204,9 +2204,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
break; break;
case STRING_CHECK: case STRING_CHECK:
if (!function->IsBuiltin() && !function_info->strict_mode()) { if (!function->IsBuiltin()) {
// Calling non-strict non-builtins with a value as the receiver // Calling non-builtins with a value as receiver requires boxing.
// requires boxing.
__ jmp(&miss); __ jmp(&miss);
} else { } else {
// Check that the object is a string or a symbol. // Check that the object is a string or a symbol.
...@@ -2221,9 +2220,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -2221,9 +2220,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
break; break;
case NUMBER_CHECK: { case NUMBER_CHECK: {
if (!function->IsBuiltin() && !function_info->strict_mode()) { if (!function->IsBuiltin()) {
// Calling non-strict non-builtins with a value as the receiver // Calling non-builtins with a value as receiver requires boxing.
// requires boxing.
__ jmp(&miss); __ jmp(&miss);
} else { } else {
Label fast; Label fast;
...@@ -2243,9 +2241,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -2243,9 +2241,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
} }
case BOOLEAN_CHECK: { case BOOLEAN_CHECK: {
if (!function->IsBuiltin() && !function_info->strict_mode()) { if (!function->IsBuiltin()) {
// Calling non-strict non-builtins with a value as the receiver // Calling non-builtins with a value as receiver requires boxing.
// requires boxing.
__ jmp(&miss); __ jmp(&miss);
} else { } else {
Label fast; Label fast;
......
...@@ -435,28 +435,16 @@ Object* CallICBase::TryCallAsFunction(Object* object) { ...@@ -435,28 +435,16 @@ Object* CallICBase::TryCallAsFunction(Object* object) {
} }
void CallICBase::ReceiverToObjectIfRequired(Object* callee, void CallICBase::ReceiverToObject(Handle<Object> object) {
Handle<Object> object) { HandleScope scope;
if (callee->IsJSFunction()) { Handle<Object> receiver(object);
JSFunction* function = JSFunction::cast(callee);
if (function->shared()->strict_mode() || function->IsBuiltin()) {
// Do not wrap receiver for strict mode functions or for builtins.
return;
}
}
if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
// And only wrap string, number or boolean.
HandleScope scope;
Handle<Object> receiver(object);
// Change the receiver to the result of calling ToObject on it. // Change the receiver to the result of calling ToObject on it.
const int argc = this->target()->arguments_count(); const int argc = this->target()->arguments_count();
StackFrameLocator locator; StackFrameLocator locator;
JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
int index = frame->ComputeExpressionsCount() - (argc + 1); int index = frame->ComputeExpressionsCount() - (argc + 1);
frame->SetExpression(index, *Factory::ToObject(object)); frame->SetExpression(index, *Factory::ToObject(object));
}
} }
...@@ -470,6 +458,10 @@ MaybeObject* CallICBase::LoadFunction(State state, ...@@ -470,6 +458,10 @@ MaybeObject* CallICBase::LoadFunction(State state,
return TypeError("non_object_property_call", object, name); return TypeError("non_object_property_call", object, name);
} }
if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
ReceiverToObject(object);
}
// Check if the name is trivially convertible to an index and get // Check if the name is trivially convertible to an index and get
// the element if so. // the element if so.
uint32_t index; uint32_t index;
...@@ -513,12 +505,6 @@ MaybeObject* CallICBase::LoadFunction(State state, ...@@ -513,12 +505,6 @@ MaybeObject* CallICBase::LoadFunction(State state,
object->GetProperty(*object, &lookup, *name, &attr); object->GetProperty(*object, &lookup, *name, &attr);
if (!maybe_result->ToObject(&result)) return maybe_result; if (!maybe_result->ToObject(&result)) return maybe_result;
} }
// Make receiver an object if the callee requires it. Strict mode or builtin
// functions do not wrap the receiver, non-strict functions and objects
// called as functions do.
ReceiverToObjectIfRequired(result, object);
if (lookup.type() == INTERCEPTOR) { if (lookup.type() == INTERCEPTOR) {
// If the object does not have the requested property, check which // If the object does not have the requested property, check which
// exception we need to throw. // exception we need to throw.
...@@ -579,8 +565,8 @@ bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, ...@@ -579,8 +565,8 @@ bool CallICBase::TryUpdateExtraICState(LookupResult* lookup,
case kStringCharAt: case kStringCharAt:
if (object->IsString()) { if (object->IsString()) {
String* string = String::cast(*object); String* string = String::cast(*object);
// Check there's the right string value or wrapper in the receiver slot. // Check that there's the right wrapper in the receiver slot.
ASSERT(string == args[0] || string == JSValue::cast(args[0])->value()); ASSERT(string == JSValue::cast(args[0])->value());
// If we're in the default (fastest) state and the index is // If we're in the default (fastest) state and the index is
// out of bounds, update the state to record this fact. // out of bounds, update the state to record this fact.
if (*extra_ic_state == DEFAULT_STRING_STUB && if (*extra_ic_state == DEFAULT_STRING_STUB &&
...@@ -789,6 +775,10 @@ MaybeObject* KeyedCallIC::LoadFunction(State state, ...@@ -789,6 +775,10 @@ MaybeObject* KeyedCallIC::LoadFunction(State state,
return TypeError("non_object_property_call", object, key); return TypeError("non_object_property_call", object, key);
} }
if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
ReceiverToObject(object);
}
if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) {
int argc = target()->arguments_count(); int argc = target()->arguments_count();
InLoopFlag in_loop = target()->ic_in_loop(); InLoopFlag in_loop = target()->ic_in_loop();
...@@ -803,17 +793,10 @@ MaybeObject* KeyedCallIC::LoadFunction(State state, ...@@ -803,17 +793,10 @@ MaybeObject* KeyedCallIC::LoadFunction(State state,
#endif #endif
} }
} }
Object* result; Object* result;
{ MaybeObject* maybe_result = Runtime::GetObjectProperty(object, key); { MaybeObject* maybe_result = Runtime::GetObjectProperty(object, key);
if (!maybe_result->ToObject(&result)) return maybe_result; if (!maybe_result->ToObject(&result)) return maybe_result;
} }
// Make receiver an object if the callee requires it. Strict mode or builtin
// functions do not wrap the receiver, non-strict functions and objects
// called as functions do.
ReceiverToObjectIfRequired(result, object);
if (result->IsJSFunction()) return result; if (result->IsJSFunction()) return result;
result = TryCallAsFunction(result); result = TryCallAsFunction(result);
MaybeObject* answer = result; MaybeObject* answer = result;
......
...@@ -224,7 +224,7 @@ class CallICBase: public IC { ...@@ -224,7 +224,7 @@ class CallICBase: public IC {
// Otherwise, it returns the undefined value. // Otherwise, it returns the undefined value.
Object* TryCallAsFunction(Object* object); Object* TryCallAsFunction(Object* object);
void ReceiverToObjectIfRequired(Object* callee, Handle<Object> object); void ReceiverToObject(Handle<Object> object);
static void Clear(Address address, Code* target); static void Clear(Address address, Code* target);
friend class IC; friend class IC;
......
...@@ -2060,9 +2060,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -2060,9 +2060,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
break; break;
case STRING_CHECK: case STRING_CHECK:
if (!function->IsBuiltin() && !function_info->strict_mode()) { if (!function->IsBuiltin()) {
// Calling non-strict non-builtins with a value as the receiver // Calling non-builtins with a value as receiver requires boxing.
// requires boxing.
__ jmp(&miss); __ jmp(&miss);
} else { } else {
// Check that the object is a two-byte string or a symbol. // Check that the object is a two-byte string or a symbol.
...@@ -2077,9 +2076,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -2077,9 +2076,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
break; break;
case NUMBER_CHECK: { case NUMBER_CHECK: {
if (!function->IsBuiltin() && !function_info->strict_mode()) { if (!function->IsBuiltin()) {
// Calling non-strict non-builtins with a value as the receiver // Calling non-builtins with a value as receiver requires boxing.
// requires boxing.
__ jmp(&miss); __ jmp(&miss);
} else { } else {
Label fast; Label fast;
...@@ -2098,9 +2096,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -2098,9 +2096,8 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
} }
case BOOLEAN_CHECK: { case BOOLEAN_CHECK: {
if (!function->IsBuiltin() && !function_info->strict_mode()) { if (!function->IsBuiltin()) {
// Calling non-strict non-builtins with a value as the receiver // Calling non-builtins with a value as receiver requires boxing.
// requires boxing.
__ jmp(&miss); __ jmp(&miss);
} else { } else {
Label fast; Label fast;
......
...@@ -438,7 +438,7 @@ repeat(10, function() { testAssignToUndefined(false); }); ...@@ -438,7 +438,7 @@ repeat(10, function() { testAssignToUndefined(false); });
})(); })();
// Not transforming this in Function.call and Function.apply. // Not transforming this in Function.call and Function.apply.
(function testThisTransformCallApply() { (function testThisTransform() {
function non_strict() { function non_strict() {
return this; return this;
} }
...@@ -478,218 +478,3 @@ repeat(10, function() { testAssignToUndefined(false); }); ...@@ -478,218 +478,3 @@ repeat(10, function() { testAssignToUndefined(false); });
assertEquals(typeof strict.apply("Hello"), "string"); assertEquals(typeof strict.apply("Hello"), "string");
assertTrue(strict.apply(object) === object); assertTrue(strict.apply(object) === object);
})(); })();
(function testThisTransform() {
try {
function strict() {
"use strict";
return typeof(this);
}
function nonstrict() {
return typeof(this);
}
// Concat to avoid symbol.
var strict_name = "str" + "ict";
var nonstrict_name = "non" + "str" + "ict";
var strict_number = 17;
var nonstrict_number = 19;
var strict_name_get = "str" + "ict" + "get";
var nonstrict_name_get = "non" + "str" + "ict" + "get"
var strict_number_get = 23;
var nonstrict_number_get = 29;
function install(t) {
t.prototype.strict = strict;
t.prototype.nonstrict = nonstrict;
t.prototype[strict_number] = strict;
t.prototype[nonstrict_number] = nonstrict;
Object.defineProperty(t.prototype, strict_name_get,
{ get: function() { return strict; },
configurable: true });
Object.defineProperty(t.prototype, nonstrict_name_get,
{ get: function() { return nonstrict; },
configurable: true });
Object.defineProperty(t.prototype, strict_number_get,
{ get: function() { return strict; },
configurable: true });
Object.defineProperty(t.prototype, nonstrict_number_get,
{ get: function() { return nonstrict; },
configurable: true });
}
function cleanup(t) {
delete t.prototype.strict;
delete t.prototype.nonstrict;
delete t.prototype[strict_number];
delete t.prototype[nonstrict_number];
delete t.prototype[strict_name_get];
delete t.prototype[nonstrict_name_get];
delete t.prototype[strict_number_get];
delete t.prototype[nonstrict_number_get];
}
// Set up fakes
install(String);
install(Number);
install(Boolean)
function callStrict(o) {
return o.strict();
}
function callNonStrict(o) {
return o.nonstrict();
}
function callKeyedStrict(o) {
return o[strict_name]();
}
function callKeyedNonStrict(o) {
return o[nonstrict_name]();
}
function callIndexedStrict(o) {
return o[strict_number]();
}
function callIndexedNonStrict(o) {
return o[nonstrict_number]();
}
function callStrictGet(o) {
return o.strictget();
}
function callNonStrictGet(o) {
return o.nonstrictget();
}
function callKeyedStrictGet(o) {
return o[strict_name_get]();
}
function callKeyedNonStrictGet(o) {
return o[nonstrict_name_get]();
}
function callIndexedStrictGet(o) {
return o[strict_number_get]();
}
function callIndexedNonStrictGet(o) {
return o[nonstrict_number_get]();
}
for (var i = 0; i < 10; i ++) {
assertEquals(("hello").strict(), "string");
assertEquals(("hello").nonstrict(), "object");
assertEquals(("hello")[strict_name](), "string");
assertEquals(("hello")[nonstrict_name](), "object");
assertEquals(("hello")[strict_number](), "string");
assertEquals(("hello")[nonstrict_number](), "object");
assertEquals((10 + i).strict(), "number");
assertEquals((10 + i).nonstrict(), "object");
assertEquals((10 + i)[strict_name](), "number");
assertEquals((10 + i)[nonstrict_name](), "object");
assertEquals((10 + i)[strict_number](), "number");
assertEquals((10 + i)[nonstrict_number](), "object");
assertEquals((true).strict(), "boolean");
assertEquals((true).nonstrict(), "object");
assertEquals((true)[strict_name](), "boolean");
assertEquals((true)[nonstrict_name](), "object");
assertEquals((true)[strict_number](), "boolean");
assertEquals((true)[nonstrict_number](), "object");
assertEquals((false).strict(), "boolean");
assertEquals((false).nonstrict(), "object");
assertEquals((false)[strict_name](), "boolean");
assertEquals((false)[nonstrict_name](), "object");
assertEquals((false)[strict_number](), "boolean");
assertEquals((false)[nonstrict_number](), "object");
assertEquals(callStrict("howdy"), "string");
assertEquals(callNonStrict("howdy"), "object");
assertEquals(callKeyedStrict("howdy"), "string");
assertEquals(callKeyedNonStrict("howdy"), "object");
assertEquals(callIndexedStrict("howdy"), "string");
assertEquals(callIndexedNonStrict("howdy"), "object");
assertEquals(callStrict(17 + i), "number");
assertEquals(callNonStrict(17 + i), "object");
assertEquals(callKeyedStrict(17 + i), "number");
assertEquals(callKeyedNonStrict(17 + i), "object");
assertEquals(callIndexedStrict(17 + i), "number");
assertEquals(callIndexedNonStrict(17 + i), "object");
assertEquals(callStrict(true), "boolean");
assertEquals(callNonStrict(true), "object");
assertEquals(callKeyedStrict(true), "boolean");
assertEquals(callKeyedNonStrict(true), "object");
assertEquals(callIndexedStrict(true), "boolean");
assertEquals(callIndexedNonStrict(true), "object");
assertEquals(callStrict(false), "boolean");
assertEquals(callNonStrict(false), "object");
assertEquals(callKeyedStrict(false), "boolean");
assertEquals(callKeyedNonStrict(false), "object");
assertEquals(callIndexedStrict(false), "boolean");
assertEquals(callIndexedNonStrict(false), "object");
// All of the above, with getters
assertEquals(("hello").strictget(), "string");
assertEquals(("hello").nonstrictget(), "object");
assertEquals(("hello")[strict_name_get](), "string");
assertEquals(("hello")[nonstrict_name_get](), "object");
assertEquals(("hello")[strict_number_get](), "string");
assertEquals(("hello")[nonstrict_number_get](), "object");
assertEquals((10 + i).strictget(), "number");
assertEquals((10 + i).nonstrictget(), "object");
assertEquals((10 + i)[strict_name_get](), "number");
assertEquals((10 + i)[nonstrict_name_get](), "object");
assertEquals((10 + i)[strict_number_get](), "number");
assertEquals((10 + i)[nonstrict_number_get](), "object");
assertEquals((true).strictget(), "boolean");
assertEquals((true).nonstrictget(), "object");
assertEquals((true)[strict_name_get](), "boolean");
assertEquals((true)[nonstrict_name_get](), "object");
assertEquals((true)[strict_number_get](), "boolean");
assertEquals((true)[nonstrict_number_get](), "object");
assertEquals((false).strictget(), "boolean");
assertEquals((false).nonstrictget(), "object");
assertEquals((false)[strict_name_get](), "boolean");
assertEquals((false)[nonstrict_name_get](), "object");
assertEquals((false)[strict_number_get](), "boolean");
assertEquals((false)[nonstrict_number_get](), "object");
assertEquals(callStrictGet("howdy"), "string");
assertEquals(callNonStrictGet("howdy"), "object");
assertEquals(callKeyedStrictGet("howdy"), "string");
assertEquals(callKeyedNonStrictGet("howdy"), "object");
assertEquals(callIndexedStrictGet("howdy"), "string");
assertEquals(callIndexedNonStrictGet("howdy"), "object");
assertEquals(callStrictGet(17 + i), "number");
assertEquals(callNonStrictGet(17 + i), "object");
assertEquals(callKeyedStrictGet(17 + i), "number");
assertEquals(callKeyedNonStrictGet(17 + i), "object");
assertEquals(callIndexedStrictGet(17 + i), "number");
assertEquals(callIndexedNonStrictGet(17 + i), "object");
assertEquals(callStrictGet(true), "boolean");
assertEquals(callNonStrictGet(true), "object");
assertEquals(callKeyedStrictGet(true), "boolean");
assertEquals(callKeyedNonStrictGet(true), "object");
assertEquals(callIndexedStrictGet(true), "boolean");
assertEquals(callIndexedNonStrictGet(true), "object");
assertEquals(callStrictGet(false), "boolean");
assertEquals(callNonStrictGet(false), "object");
assertEquals(callKeyedStrictGet(false), "boolean");
assertEquals(callKeyedNonStrictGet(false), "object");
assertEquals(callIndexedStrictGet(false), "boolean");
assertEquals(callIndexedNonStrictGet(false), "object");
}
} finally {
// Cleanup
cleanup(String);
cleanup(Number);
cleanup(Boolean);
}
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment