Commit d49d3864 authored by jgruber's avatar jgruber Committed by Commit bot

[builtins] Construct builtin frame in String/Number ctors

BUG=v8:5173
R=bmeurer@chromium.org

Review-Url: https://codereview.chromium.org/2118283003
Cr-Commit-Position: refs/heads/master@{#37598}
parent 1f53e42b
This diff is collapsed.
......@@ -1284,6 +1284,19 @@ int MacroAssembler::LeaveFrame(StackFrame::Type type) {
return frame_ends;
}
void MacroAssembler::EnterBuiltinFrame(Register context, Register target,
Register argc) {
Push(lr, fp, context, target);
add(fp, sp, Operand(2 * kPointerSize));
Push(argc);
}
void MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
Register argc) {
Pop(argc);
Pop(lr, fp, context, target);
}
void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
StackFrame::Type frame_type) {
DCHECK(frame_type == StackFrame::EXIT ||
......
......@@ -1438,6 +1438,9 @@ class MacroAssembler: public Assembler {
// Returns the pc offset at which the frame ends.
int LeaveFrame(StackFrame::Type type);
void EnterBuiltinFrame(Register context, Register target, Register argc);
void LeaveBuiltinFrame(Register context, Register target, Register argc);
// Expects object in r0 and returns map with validated enum cache
// in r0. Assumes that any other register can be used as a scratch.
void CheckEnumCache(Label* call_runtime);
......
This diff is collapsed.
......@@ -2823,6 +2823,19 @@ void MacroAssembler::ExitFrameRestoreFPRegs() {
}
}
void MacroAssembler::EnterBuiltinFrame(Register context, Register target,
Register argc) {
Push(lr, fp, context, target);
add(fp, jssp, Operand(2 * kPointerSize));
Push(argc);
}
void MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
Register argc) {
Pop(argc);
Pop(target, context, fp, lr);
}
void MacroAssembler::EnterExitFrame(bool save_doubles, const Register& scratch,
int extra_space,
StackFrame::Type frame_type) {
......
......@@ -1642,6 +1642,9 @@ class MacroAssembler : public Assembler {
void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg);
void LeaveFrame(StackFrame::Type type);
void EnterBuiltinFrame(Register context, Register target, Register argc);
void LeaveBuiltinFrame(Register context, Register target, Register argc);
// Returns map with validated enum cache in object register.
void CheckEnumCache(Register object, Register scratch0, Register scratch1,
Register scratch2, Register scratch3, Register scratch4,
......
This diff is collapsed.
......@@ -1130,6 +1130,23 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
leave();
}
void MacroAssembler::EnterBuiltinFrame(Register context, Register target,
Register argc) {
Push(ebp);
Move(ebp, esp);
Push(context);
Push(target);
Push(argc);
}
void MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
Register argc) {
Pop(argc);
Pop(target);
Pop(context);
leave();
}
void MacroAssembler::EnterExitFramePrologue(StackFrame::Type frame_type) {
DCHECK(frame_type == StackFrame::EXIT ||
frame_type == StackFrame::BUILTIN_EXIT);
......
......@@ -932,6 +932,9 @@ class MacroAssembler: public Assembler {
void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg);
void LeaveFrame(StackFrame::Type type);
void EnterBuiltinFrame(Register context, Register target, Register argc);
void LeaveBuiltinFrame(Register context, Register target, Register argc);
// Expects object in eax and returns map with validated enum cache
// in eax. Assumes that any other register can be used as a scratch.
void CheckEnumCache(Label* call_runtime);
......
This diff is collapsed.
......@@ -5911,6 +5911,19 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
lw(fp, MemOperand(fp, 0 * kPointerSize));
}
void MacroAssembler::EnterBuiltinFrame(Register context, Register target,
Register argc) {
Push(ra, fp);
Move(fp, sp);
Push(context, target, argc);
}
void MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
Register argc) {
Pop(context, target, argc);
Pop(ra, fp);
}
void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
StackFrame::Type frame_type) {
DCHECK(frame_type == StackFrame::EXIT ||
......
......@@ -1720,6 +1720,9 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg);
void LeaveFrame(StackFrame::Type type);
void EnterBuiltinFrame(Register context, Register target, Register argc);
void LeaveBuiltinFrame(Register context, Register target, Register argc);
// Expects object in a0 and returns map with validated enum cache
// in a0. Assumes that any other register can be used as a scratch.
void CheckEnumCache(Label* call_runtime);
......
This diff is collapsed.
......@@ -6182,6 +6182,19 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
ld(fp, MemOperand(fp, 0 * kPointerSize));
}
void MacroAssembler::EnterBuiltinFrame(Register context, Register target,
Register argc) {
Push(ra, fp);
Move(fp, sp);
Push(context, target, argc);
}
void MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
Register argc) {
Pop(context, target, argc);
Pop(ra, fp);
}
void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
StackFrame::Type frame_type) {
DCHECK(frame_type == StackFrame::EXIT ||
......
......@@ -1853,6 +1853,9 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg);
void LeaveFrame(StackFrame::Type type);
void EnterBuiltinFrame(Register context, Register target, Register argc);
void LeaveBuiltinFrame(Register context, Register target, Register argc);
// Expects object in a0 and returns map with validated enum cache
// in a0. Assumes that any other register can be used as a scratch.
void CheckEnumCache(Label* call_runtime);
......
This diff is collapsed.
......@@ -4436,6 +4436,23 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
popq(rbp);
}
void MacroAssembler::EnterBuiltinFrame(Register context, Register target,
Register argc) {
Push(rbp);
Move(rbp, rsp);
Push(context);
Push(target);
Push(argc);
}
void MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
Register argc) {
Pop(argc);
Pop(target);
Pop(context);
leave();
}
void MacroAssembler::EnterExitFramePrologue(bool save_rax,
StackFrame::Type frame_type) {
DCHECK(frame_type == StackFrame::EXIT ||
......
......@@ -1575,6 +1575,9 @@ class MacroAssembler: public Assembler {
void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg);
void LeaveFrame(StackFrame::Type type);
void EnterBuiltinFrame(Register context, Register target, Register argc);
void LeaveBuiltinFrame(Register context, Register target, Register argc);
// Expects object in rax and returns map with validated enum cache
// in rax. Assumes that any other register can be used as a scratch.
void CheckEnumCache(Label* call_runtime);
......
......@@ -114,6 +114,9 @@
# Assumptions about optimization need investigation in TurboFan.
'regress-sync-optimized-lists': [PASS, NO_VARIANTS],
# Fails in --turbo --always-opt mode.
'regress/regress-105': [PASS, NO_VARIANTS],
##############################################################################
# Too slow in debug mode with --stress-opt mode.
'compiler/regress-stacktrace-methods': [PASS, ['mode == debug', SKIP]],
......
......@@ -26,12 +26,12 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
var custom_valueOf = function() {
assertEquals(null, custom_valueOf.caller);
assertEquals(Number, custom_valueOf.caller);
return 2;
}
var custom_toString = function() {
assertEquals(null, custom_toString.caller);
assertEquals(String, custom_toString.caller);
return "I used to be an adventurer like you";
}
......
......@@ -16,9 +16,6 @@ function testTraceNativeConversion(nativeFunc) {
}
}
testTraceNativeConversion(Math.max);
testTraceNativeConversion(Math.min);
// C++ builtins.
testTraceNativeConversion(Math.acos);
testTraceNativeConversion(Math.asin);
......@@ -35,15 +32,6 @@ function testBuiltinInStackTrace(script, expectedString) {
}
}
// Use the full name ('String.getDate') in order to avoid false pass
// results when the method name is mentioned in the error message itself.
// This occurs, e.g., for Date.prototype.getYear, which uses a different code
// path and never hits the Generate_DatePrototype_GetField builtin.
testBuiltinInStackTrace("Date.prototype.getDate.call('')", "at String.getDate");
testBuiltinInStackTrace("Date.prototype.getUTCDate.call('')",
"at String.getUTCDate");
testBuiltinInStackTrace("Date.prototype.getTime.call('')", "at String.getTime");
// C++ builtins.
testBuiltinInStackTrace("Boolean.prototype.toString.call(thrower);",
"at Object.toString");
......@@ -52,16 +40,12 @@ testBuiltinInStackTrace("Boolean.prototype.toString.call(thrower);",
testBuiltinInStackTrace("new Date(thrower);", "at new Date");
// Ensure we correctly pick up the receiver's string tag.
testBuiltinInStackTrace("Math.max(thrower);", "at Math.max");
testBuiltinInStackTrace("Math.min(thrower);", "at Math.min");
testBuiltinInStackTrace("Math.acos(thrower);", "at Math.acos");
testBuiltinInStackTrace("Math.asin(thrower);", "at Math.asin");
testBuiltinInStackTrace("Math.fround(thrower);", "at Math.fround");
testBuiltinInStackTrace("Math.imul(thrower);", "at Math.imul");
// As above, but function passed as an argument and then called.
testBuiltinInStackTrace("((f, x) => f(x))(Math.max, thrower);", "at max");
testBuiltinInStackTrace("((f, x) => f(x))(Math.min, thrower);", "at min");
testBuiltinInStackTrace("((f, x) => f(x))(Math.acos, thrower);", "at acos");
testBuiltinInStackTrace("((f, x) => f(x))(Math.asin, thrower);", "at asin");
testBuiltinInStackTrace("((f, x) => f(x))(Math.fround, thrower);", "at fround");
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var thrower = { [Symbol.toPrimitive]: () => FAIL };
// Tests that a native conversion function is included in the
// stack trace.
function testTraceNativeConversion(nativeFunc) {
var nativeFuncName = nativeFunc.name;
try {
nativeFunc(thrower);
assertUnreachable(nativeFuncName);
} catch (e) {
assertTrue(e.stack.indexOf(nativeFuncName) >= 0, nativeFuncName);
}
}
testTraceNativeConversion(Math.max);
testTraceNativeConversion(Math.min);
function testBuiltinInStackTrace(script, expectedString) {
try {
eval(script);
assertUnreachable(expectedString);
} catch (e) {
assertTrue(e.stack.indexOf(expectedString) >= 0, expectedString);
}
}
testBuiltinInStackTrace("Date.prototype.getDate.call('')", "at String.getDate");
testBuiltinInStackTrace("Date.prototype.getUTCDate.call('')",
"at String.getUTCDate");
testBuiltinInStackTrace("Date.prototype.getTime.call('')", "at String.getTime");
// TODO(jgruber): These use a more generic expected string until detection of
// assembly builtin constructors is fixed.
testBuiltinInStackTrace("Number(thrower);", "Number");
testBuiltinInStackTrace("new Number(thrower);", "Number");
testBuiltinInStackTrace("String(thrower);", "String");
testBuiltinInStackTrace("new String(thrower);", "String");
// Ensure we correctly pick up the receiver's string tag.
testBuiltinInStackTrace("Math.acos(thrower);", "at Math.acos");
testBuiltinInStackTrace("Math.asin(thrower);", "at Math.asin");
testBuiltinInStackTrace("Math.fround(thrower);", "at Math.fround");
testBuiltinInStackTrace("Math.imul(thrower);", "at Math.imul");
// As above, but function passed as an argument and then called.
testBuiltinInStackTrace("((f, x) => f(x))(Math.acos, thrower);", "at acos");
testBuiltinInStackTrace("((f, x) => f(x))(Math.asin, thrower);", "at asin");
testBuiltinInStackTrace("((f, x) => f(x))(Math.fround, thrower);", "at fround");
testBuiltinInStackTrace("((f, x) => f(x))(Math.imul, thrower);", "at imul");
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