Fix inlining of strict mode constructors.
Inlined strict mode functions (that are not called as methods) will get their receiver reset to undefined. This should not happen when inlining constructors. This change also simplifies the test suite to reuse the same closures into which constructors get inlined and use gc() to force V8 to forget collected type feedback. R=vegorov@chromium.org TEST=mjsunit/compiler/inline-construct Review URL: https://chromiumcodereview.appspot.com/9597017 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10920 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
98b12bc085
commit
240e818f0c
@ -7693,7 +7693,7 @@ HEnvironment* HEnvironment::CopyForInlining(
|
||||
// builtin function, pass undefined as the receiver for function
|
||||
// calls (instead of the global receiver).
|
||||
if ((target->shared()->native() || !function->is_classic_mode()) &&
|
||||
call_kind == CALL_AS_FUNCTION) {
|
||||
call_kind == CALL_AS_FUNCTION && !is_construct) {
|
||||
inner->SetValueAt(0, undefined);
|
||||
}
|
||||
inner->SetValueAt(arity + 1, LookupContext());
|
||||
|
@ -25,7 +25,7 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --allow-natives-syntax --inline-construct
|
||||
// Flags: --allow-natives-syntax --expose-gc --inline-construct
|
||||
|
||||
// Test inlining of constructor calls.
|
||||
|
||||
@ -47,29 +47,37 @@ function TestInlinedConstructor(closure) {
|
||||
assertEquals(4, counter.value);
|
||||
}
|
||||
|
||||
function TestInAllContexts(constructor) {
|
||||
function value_context(a, b, counter) {
|
||||
var obj = new constructor(a, b, counter);
|
||||
return obj.x;
|
||||
}
|
||||
function test_context(a, b, counter) {
|
||||
if (!new constructor(a, b, counter)) {
|
||||
assertUnreachable("should not happen");
|
||||
}
|
||||
return a + b;
|
||||
}
|
||||
function effect_context(a, b, counter) {
|
||||
new constructor(a, b, counter);
|
||||
return a + b;
|
||||
}
|
||||
TestInlinedConstructor(value_context);
|
||||
TestInlinedConstructor(test_context);
|
||||
TestInlinedConstructor(effect_context);
|
||||
%DeoptimizeFunction(value_context);
|
||||
%DeoptimizeFunction(test_context);
|
||||
%DeoptimizeFunction(effect_context);
|
||||
gc(); // Makes V8 forget about type information for *_context.
|
||||
}
|
||||
|
||||
|
||||
// Test constructor returning nothing in all contexts.
|
||||
function c1(a, b, counter) {
|
||||
this.x = a + b;
|
||||
counter.value++;
|
||||
}
|
||||
function c1_value_context(a, b, counter) {
|
||||
var obj = new c1(a, b, counter);
|
||||
return obj.x;
|
||||
}
|
||||
function c1_test_context(a, b, counter) {
|
||||
if (!new c1(a, b, counter)) {
|
||||
assertUnreachable("should not happen");
|
||||
}
|
||||
return a + b;
|
||||
}
|
||||
function c1_effect_context(a, b, counter) {
|
||||
new c1(a, b, counter);
|
||||
return a + b;
|
||||
}
|
||||
TestInlinedConstructor(c1_value_context);
|
||||
TestInlinedConstructor(c1_test_context);
|
||||
TestInlinedConstructor(c1_effect_context);
|
||||
TestInAllContexts(c1);
|
||||
|
||||
|
||||
// Test constructor returning an object in all contexts.
|
||||
@ -79,23 +87,7 @@ function c2(a, b, counter) {
|
||||
counter.value++;
|
||||
return obj;
|
||||
}
|
||||
function c2_value_context(a, b, counter) {
|
||||
var obj = new c2(a, b, counter);
|
||||
return obj.x;
|
||||
}
|
||||
function c2_test_context(a, b, counter) {
|
||||
if (!new c2(a, b, counter)) {
|
||||
assertUnreachable("should not happen");
|
||||
}
|
||||
return a + b;
|
||||
}
|
||||
function c2_effect_context(a, b, counter) {
|
||||
new c2(a, b, counter);
|
||||
return a + b;
|
||||
}
|
||||
TestInlinedConstructor(c2_value_context);
|
||||
TestInlinedConstructor(c2_test_context);
|
||||
TestInlinedConstructor(c2_effect_context);
|
||||
TestInAllContexts(c2);
|
||||
|
||||
|
||||
// Test constructor returning a primitive value in all contexts.
|
||||
@ -104,23 +96,7 @@ function c3(a, b, counter) {
|
||||
counter.value++;
|
||||
return "not an object";
|
||||
}
|
||||
function c3_value_context(a, b, counter) {
|
||||
var obj = new c3(a, b, counter);
|
||||
return obj.x;
|
||||
}
|
||||
function c3_test_context(a, b, counter) {
|
||||
if (!new c3(a, b, counter)) {
|
||||
assertUnreachable("should not happen");
|
||||
}
|
||||
return a + b;
|
||||
}
|
||||
function c3_effect_context(a, b, counter) {
|
||||
new c3(a, b, counter);
|
||||
return a + b;
|
||||
}
|
||||
TestInlinedConstructor(c3_value_context);
|
||||
TestInlinedConstructor(c3_test_context);
|
||||
TestInlinedConstructor(c3_effect_context);
|
||||
TestInAllContexts(c3);
|
||||
|
||||
|
||||
// Test constructor called with too many arguments.
|
||||
@ -163,8 +139,14 @@ function c_unsupported_syntax(a, b, counter) {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
function f_unsupported_syntax(a, b, counter) {
|
||||
var obj = new c_unsupported_syntax(a, b, counter);
|
||||
return obj.x;
|
||||
TestInAllContexts(c_unsupported_syntax);
|
||||
|
||||
|
||||
// Regression test: Inlined constructors called as functions do not get their
|
||||
// implicit receiver object set to undefined, even in strict mode.
|
||||
function c_strict(a, b, counter) {
|
||||
"use strict";
|
||||
this.x = a + b;
|
||||
counter.value++;
|
||||
}
|
||||
TestInlinedConstructor(f_unsupported_syntax);
|
||||
TestInAllContexts(c_strict);
|
||||
|
Loading…
Reference in New Issue
Block a user