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) { ...@@ -1284,6 +1284,19 @@ int MacroAssembler::LeaveFrame(StackFrame::Type type) {
return frame_ends; 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, void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
StackFrame::Type frame_type) { StackFrame::Type frame_type) {
DCHECK(frame_type == StackFrame::EXIT || DCHECK(frame_type == StackFrame::EXIT ||
......
...@@ -1438,6 +1438,9 @@ class MacroAssembler: public Assembler { ...@@ -1438,6 +1438,9 @@ class MacroAssembler: public Assembler {
// Returns the pc offset at which the frame ends. // Returns the pc offset at which the frame ends.
int LeaveFrame(StackFrame::Type type); 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 // Expects object in r0 and returns map with validated enum cache
// in r0. Assumes that any other register can be used as a scratch. // in r0. Assumes that any other register can be used as a scratch.
void CheckEnumCache(Label* call_runtime); void CheckEnumCache(Label* call_runtime);
......
This diff is collapsed.
...@@ -2823,6 +2823,19 @@ void MacroAssembler::ExitFrameRestoreFPRegs() { ...@@ -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, void MacroAssembler::EnterExitFrame(bool save_doubles, const Register& scratch,
int extra_space, int extra_space,
StackFrame::Type frame_type) { StackFrame::Type frame_type) {
......
...@@ -1642,6 +1642,9 @@ class MacroAssembler : public Assembler { ...@@ -1642,6 +1642,9 @@ class MacroAssembler : public Assembler {
void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg); void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg);
void LeaveFrame(StackFrame::Type type); 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. // Returns map with validated enum cache in object register.
void CheckEnumCache(Register object, Register scratch0, Register scratch1, void CheckEnumCache(Register object, Register scratch0, Register scratch1,
Register scratch2, Register scratch3, Register scratch4, Register scratch2, Register scratch3, Register scratch4,
......
This diff is collapsed.
...@@ -1130,6 +1130,23 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) { ...@@ -1130,6 +1130,23 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
leave(); 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) { void MacroAssembler::EnterExitFramePrologue(StackFrame::Type frame_type) {
DCHECK(frame_type == StackFrame::EXIT || DCHECK(frame_type == StackFrame::EXIT ||
frame_type == StackFrame::BUILTIN_EXIT); frame_type == StackFrame::BUILTIN_EXIT);
......
...@@ -932,6 +932,9 @@ class MacroAssembler: public Assembler { ...@@ -932,6 +932,9 @@ class MacroAssembler: public Assembler {
void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg); void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg);
void LeaveFrame(StackFrame::Type type); 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 // Expects object in eax and returns map with validated enum cache
// in eax. Assumes that any other register can be used as a scratch. // in eax. Assumes that any other register can be used as a scratch.
void CheckEnumCache(Label* call_runtime); void CheckEnumCache(Label* call_runtime);
......
This diff is collapsed.
...@@ -5911,6 +5911,19 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) { ...@@ -5911,6 +5911,19 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
lw(fp, MemOperand(fp, 0 * kPointerSize)); 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, void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
StackFrame::Type frame_type) { StackFrame::Type frame_type) {
DCHECK(frame_type == StackFrame::EXIT || DCHECK(frame_type == StackFrame::EXIT ||
......
...@@ -1720,6 +1720,9 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT ...@@ -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 EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg);
void LeaveFrame(StackFrame::Type type); 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 // Expects object in a0 and returns map with validated enum cache
// in a0. Assumes that any other register can be used as a scratch. // in a0. Assumes that any other register can be used as a scratch.
void CheckEnumCache(Label* call_runtime); void CheckEnumCache(Label* call_runtime);
......
This diff is collapsed.
...@@ -6182,6 +6182,19 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) { ...@@ -6182,6 +6182,19 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
ld(fp, MemOperand(fp, 0 * kPointerSize)); 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, void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
StackFrame::Type frame_type) { StackFrame::Type frame_type) {
DCHECK(frame_type == StackFrame::EXIT || DCHECK(frame_type == StackFrame::EXIT ||
......
...@@ -1853,6 +1853,9 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT ...@@ -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 EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg);
void LeaveFrame(StackFrame::Type type); 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 // Expects object in a0 and returns map with validated enum cache
// in a0. Assumes that any other register can be used as a scratch. // in a0. Assumes that any other register can be used as a scratch.
void CheckEnumCache(Label* call_runtime); void CheckEnumCache(Label* call_runtime);
......
This diff is collapsed.
...@@ -4436,6 +4436,23 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) { ...@@ -4436,6 +4436,23 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
popq(rbp); 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, void MacroAssembler::EnterExitFramePrologue(bool save_rax,
StackFrame::Type frame_type) { StackFrame::Type frame_type) {
DCHECK(frame_type == StackFrame::EXIT || DCHECK(frame_type == StackFrame::EXIT ||
......
...@@ -1575,6 +1575,9 @@ class MacroAssembler: public Assembler { ...@@ -1575,6 +1575,9 @@ class MacroAssembler: public Assembler {
void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg); void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg);
void LeaveFrame(StackFrame::Type type); 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 // Expects object in rax and returns map with validated enum cache
// in rax. Assumes that any other register can be used as a scratch. // in rax. Assumes that any other register can be used as a scratch.
void CheckEnumCache(Label* call_runtime); void CheckEnumCache(Label* call_runtime);
......
...@@ -114,6 +114,9 @@ ...@@ -114,6 +114,9 @@
# Assumptions about optimization need investigation in TurboFan. # Assumptions about optimization need investigation in TurboFan.
'regress-sync-optimized-lists': [PASS, NO_VARIANTS], '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. # Too slow in debug mode with --stress-opt mode.
'compiler/regress-stacktrace-methods': [PASS, ['mode == debug', SKIP]], 'compiler/regress-stacktrace-methods': [PASS, ['mode == debug', SKIP]],
......
...@@ -26,12 +26,12 @@ ...@@ -26,12 +26,12 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
var custom_valueOf = function() { var custom_valueOf = function() {
assertEquals(null, custom_valueOf.caller); assertEquals(Number, custom_valueOf.caller);
return 2; return 2;
} }
var custom_toString = function() { var custom_toString = function() {
assertEquals(null, custom_toString.caller); assertEquals(String, custom_toString.caller);
return "I used to be an adventurer like you"; return "I used to be an adventurer like you";
} }
......
...@@ -16,9 +16,6 @@ function testTraceNativeConversion(nativeFunc) { ...@@ -16,9 +16,6 @@ function testTraceNativeConversion(nativeFunc) {
} }
} }
testTraceNativeConversion(Math.max);
testTraceNativeConversion(Math.min);
// C++ builtins. // C++ builtins.
testTraceNativeConversion(Math.acos); testTraceNativeConversion(Math.acos);
testTraceNativeConversion(Math.asin); testTraceNativeConversion(Math.asin);
...@@ -35,15 +32,6 @@ function testBuiltinInStackTrace(script, expectedString) { ...@@ -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. // C++ builtins.
testBuiltinInStackTrace("Boolean.prototype.toString.call(thrower);", testBuiltinInStackTrace("Boolean.prototype.toString.call(thrower);",
"at Object.toString"); "at Object.toString");
...@@ -52,16 +40,12 @@ testBuiltinInStackTrace("Boolean.prototype.toString.call(thrower);", ...@@ -52,16 +40,12 @@ testBuiltinInStackTrace("Boolean.prototype.toString.call(thrower);",
testBuiltinInStackTrace("new Date(thrower);", "at new Date"); testBuiltinInStackTrace("new Date(thrower);", "at new Date");
// Ensure we correctly pick up the receiver's string tag. // 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.acos(thrower);", "at Math.acos");
testBuiltinInStackTrace("Math.asin(thrower);", "at Math.asin"); testBuiltinInStackTrace("Math.asin(thrower);", "at Math.asin");
testBuiltinInStackTrace("Math.fround(thrower);", "at Math.fround"); testBuiltinInStackTrace("Math.fround(thrower);", "at Math.fround");
testBuiltinInStackTrace("Math.imul(thrower);", "at Math.imul"); testBuiltinInStackTrace("Math.imul(thrower);", "at Math.imul");
// As above, but function passed as an argument and then called. // 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.acos, thrower);", "at acos");
testBuiltinInStackTrace("((f, x) => f(x))(Math.asin, thrower);", "at asin"); 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.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