Correctly annotate eval origin.

There were a couple of issues with it:
- interpreter is not supported
- the source position was just accidentally correct for full-codegen
- the eval origin could have been cached

Also fixes a few other places to use AbstractCode.

R=mstarzinger@chromium.org

Committed: https://crrev.com/2f3a171adc9e620c2235bf0562145b9d4eaba66d
Cr-Commit-Position: refs/heads/master@{#35257}

Committed: https://crrev.com/ad4e8a27963b704bb70ec8bac0991c57296b1d16
Cr-Commit-Position: refs/heads/master@{#35481}

Review URL: https://codereview.chromium.org/1854713002

Cr-Commit-Position: refs/heads/master@{#35581}
This commit is contained in:
yangguo 2016-04-18 06:20:45 -07:00 committed by Commit bot
parent 31e4644682
commit 89d7bfda0d
34 changed files with 224 additions and 154 deletions

View File

@ -661,11 +661,8 @@ void Accessors::ScriptEvalFromScriptPositionGetter(
Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
Handle<Object> result = isolate->factory()->undefined_value();
if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
Handle<Code> code(SharedFunctionInfo::cast(
script->eval_from_shared())->code());
result = Handle<Object>(Smi::FromInt(code->SourcePosition(
script->eval_from_instructions_offset())),
isolate);
result =
Handle<Object>(Smi::FromInt(script->eval_from_position()), isolate);
}
info.GetReturnValue().Set(Utils::ToLocal(result));
}

View File

@ -2033,6 +2033,8 @@ MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext(
}
i::Handle<i::Object> name_obj;
int eval_scope_position = 0;
int eval_position = i::RelocInfo::kNoPosition;
int line_offset = 0;
int column_offset = 0;
if (!source->resource_name.IsEmpty()) {
@ -2045,11 +2047,13 @@ MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext(
column_offset = static_cast<int>(source->resource_column_offset->Value());
}
i::Handle<i::JSFunction> fun;
has_pending_exception = !i::Compiler::GetFunctionFromEval(
source_string, outer_info, context, i::SLOPPY,
i::ONLY_SINGLE_FUNCTION_LITERAL, line_offset,
column_offset - scope_position, name_obj,
source->resource_options).ToHandle(&fun);
has_pending_exception =
!i::Compiler::GetFunctionFromEval(
source_string, outer_info, context, i::SLOPPY,
i::ONLY_SINGLE_FUNCTION_LITERAL, eval_scope_position, eval_position,
line_offset, column_offset - scope_position, name_obj,
source->resource_options)
.ToHandle(&fun);
if (has_pending_exception) {
isolate->ReportPendingMessages();
}

View File

@ -2067,11 +2067,22 @@ MaybeHandle<JSFunction> CompileString(Handle<Context> context,
}
// Compile source string in the native context.
Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared(),
isolate);
StackTraceFrameIterator it(isolate);
int eval_scope_position = 0;
int eval_position = RelocInfo::kNoPosition;
Handle<SharedFunctionInfo> outer_info;
if (!it.done() && it.is_javascript()) {
FrameSummary summary = FrameSummary::GetFirst(it.javascript_frame());
eval_position =
summary.abstract_code()->SourcePosition(summary.code_offset());
outer_info = Handle<SharedFunctionInfo>(summary.function()->shared());
} else {
outer_info =
Handle<SharedFunctionInfo>(native_context->closure()->shared());
}
return Compiler::GetFunctionFromEval(source, outer_info, native_context,
SLOPPY, restriction,
RelocInfo::kNoPosition);
SLOPPY, restriction, eval_scope_position,
eval_position);
}
} // namespace

View File

@ -1212,8 +1212,9 @@ void Compiler::CompileForLiveEdit(Handle<Script> script) {
MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
Handle<String> source, Handle<SharedFunctionInfo> outer_info,
Handle<Context> context, LanguageMode language_mode,
ParseRestriction restriction, int line_offset, int column_offset,
Handle<Object> script_name, ScriptOriginOptions options) {
ParseRestriction restriction, int eval_scope_position, int eval_position,
int line_offset, int column_offset, Handle<Object> script_name,
ScriptOriginOptions options) {
Isolate* isolate = source->GetIsolate();
int source_length = source->length();
isolate->counters()->total_eval_size()->Increment(source_length);
@ -1222,7 +1223,7 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
CompilationCache* compilation_cache = isolate->compilation_cache();
MaybeHandle<SharedFunctionInfo> maybe_shared_info =
compilation_cache->LookupEval(source, outer_info, context, language_mode,
line_offset);
eval_scope_position);
Handle<SharedFunctionInfo> shared_info;
Handle<Script> script;
@ -1234,6 +1235,10 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
script->set_column_offset(column_offset);
}
script->set_origin_options(options);
script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
script->set_eval_from_shared(*outer_info);
script->set_eval_from_position(eval_position);
Zone zone(isolate->allocator());
ParseInfo parse_info(&zone, script);
CompilationInfo info(&parse_info, Handle<JSFunction>::null());
@ -1243,8 +1248,6 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
parse_info.set_parse_restriction(restriction);
parse_info.set_context(context);
Debug::RecordEvalCaller(script);
shared_info = CompileToplevel(&info);
if (shared_info.is_null()) {
@ -1260,7 +1263,7 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
DCHECK(is_sloppy(language_mode) ||
is_strict(shared_info->language_mode()));
compilation_cache->PutEval(source, outer_info, context, shared_info,
line_offset);
eval_scope_position);
}
}

View File

@ -77,7 +77,8 @@ class Compiler : public AllStatic {
MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
Handle<String> source, Handle<SharedFunctionInfo> outer_info,
Handle<Context> context, LanguageMode language_mode,
ParseRestriction restriction, int line_offset, int column_offset = 0,
ParseRestriction restriction, int eval_scope_position, int eval_position,
int line_offset = 0, int column_offset = 0,
Handle<Object> script_name = Handle<Object>(),
ScriptOriginOptions options = ScriptOriginOptions());

View File

@ -2456,11 +2456,13 @@ void AstGraphBuilder::VisitCall(Call* expr) {
// provide a fully resolved callee to patch into the environment.
Node* function = GetFunctionClosure();
Node* language = jsgraph()->Constant(language_mode());
Node* position = jsgraph()->Constant(current_scope()->start_position());
Node* eval_scope_position =
jsgraph()->Constant(current_scope()->start_position());
Node* eval_position = jsgraph()->Constant(expr->position());
const Operator* op =
javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval);
Node* new_callee =
NewNode(op, callee, source, function, language, position);
Node* new_callee = NewNode(op, callee, source, function, language,
eval_scope_position, eval_position);
PrepareFrameState(new_callee, expr->EvalId(),
OutputFrameStateCombine::PokeAt(arg_count + 1));

View File

@ -95,11 +95,12 @@ MaybeHandle<Object> DebugEvaluate::Evaluate(
}
Handle<JSFunction> eval_fun;
ASSIGN_RETURN_ON_EXCEPTION(isolate, eval_fun,
Compiler::GetFunctionFromEval(
source, outer_info, context, SLOPPY,
NO_PARSE_RESTRICTION, RelocInfo::kNoPosition),
Object);
ASSIGN_RETURN_ON_EXCEPTION(
isolate, eval_fun,
Compiler::GetFunctionFromEval(
source, outer_info, context, SLOPPY, NO_PARSE_RESTRICTION,
RelocInfo::kNoPosition, RelocInfo::kNoPosition),
Object);
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(

View File

@ -72,8 +72,7 @@ int FrameInspector::GetSourcePosition() {
return deoptimized_frame_->GetSourcePosition();
} else if (is_interpreted_) {
InterpretedFrame* frame = reinterpret_cast<InterpretedFrame*>(frame_);
BytecodeArray* bytecode_array =
frame->function()->shared()->bytecode_array();
BytecodeArray* bytecode_array = frame->GetBytecodeArray();
return bytecode_array->SourcePosition(frame->GetBytecodeOffset());
} else {
Code* code = frame_->LookupCode();

View File

@ -260,12 +260,6 @@ BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info,
return it->GetBreakLocation();
}
FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) {
List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
frame->Summarize(&frames);
return frames.first();
}
int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) {
// Code offset points to the instruction after the call. Subtract 1 to
// exclude that instruction from the search. For bytecode, the code offset
@ -275,7 +269,7 @@ int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) {
BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
JavaScriptFrame* frame) {
FrameSummary summary = GetFirstFrameSummary(frame);
FrameSummary summary = FrameSummary::GetFirst(frame);
int call_offset =
CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted());
return FromCodeOffset(debug_info, call_offset);
@ -631,7 +625,7 @@ void Debug::Break(JavaScriptFrame* frame) {
step_break = location.IsTailCall();
// Fall through.
case StepIn: {
FrameSummary summary = GetFirstFrameSummary(frame);
FrameSummary summary = FrameSummary::GetFirst(frame);
int offset = summary.code_offset();
step_break = step_break || location.IsReturn() ||
(current_fp != last_fp) ||
@ -1011,7 +1005,7 @@ void Debug::PrepareStep(StepAction step_action) {
}
// Get the debug info (create it if it does not exist).
FrameSummary summary = GetFirstFrameSummary(frame);
FrameSummary summary = FrameSummary::GetFirst(frame);
Handle<JSFunction> function(summary.function());
Handle<SharedFunctionInfo> shared(function->shared());
if (!EnsureDebugInfo(shared, function)) {
@ -1022,7 +1016,7 @@ void Debug::PrepareStep(StepAction step_action) {
Handle<DebugInfo> debug_info(shared->GetDebugInfo());
// Refresh frame summary if the code has been recompiled for debugging.
if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) {
summary = GetFirstFrameSummary(frame);
summary = FrameSummary::GetFirst(frame);
}
int call_offset =
@ -1604,7 +1598,7 @@ bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
if (!shared->HasDebugInfo()) return false;
DCHECK(!frame->is_optimized());
FrameSummary summary = GetFirstFrameSummary(frame);
FrameSummary summary = FrameSummary::GetFirst(frame);
Handle<DebugInfo> debug_info(shared->GetDebugInfo());
BreakLocation location =
@ -1656,21 +1650,6 @@ Handle<FixedArray> Debug::GetLoadedScripts() {
}
void Debug::RecordEvalCaller(Handle<Script> script) {
script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
// For eval scripts add information on the function from which eval was
// called.
StackTraceFrameIterator it(script->GetIsolate());
if (!it.done()) {
script->set_eval_from_shared(it.frame()->function()->shared());
Code* code = it.frame()->LookupCode();
int offset = static_cast<int>(
it.frame()->pc() - code->instruction_start());
script->set_eval_from_instructions_offset(offset);
}
}
MaybeHandle<Object> Debug::MakeExecutionState() {
// Create the execution state object.
Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
@ -2260,7 +2239,7 @@ void Debug::PrintBreakLocation() {
JavaScriptFrameIterator iterator(isolate_);
if (iterator.done()) return;
JavaScriptFrame* frame = iterator.frame();
FrameSummary summary = GetFirstFrameSummary(frame);
FrameSummary summary = FrameSummary::GetFirst(frame);
int source_position =
summary.abstract_code()->SourcePosition(summary.code_offset());
Handle<Object> script_obj(summary.function()->shared()->script(), isolate_);

View File

@ -498,9 +498,6 @@ class Debug {
static int ArchiveSpacePerThread();
void FreeThreadResources() { }
// Record function from which eval was called.
static void RecordEvalCaller(Handle<Script> script);
bool CheckExecutionState(int id) {
return is_active() && !debug_context().is_null() && break_id() != 0 &&
break_id() == id;

View File

@ -1374,8 +1374,7 @@ static Handle<Script> CreateScriptCopy(Handle<Script> original) {
copy->set_type(original->type());
copy->set_context_data(original->context_data());
copy->set_eval_from_shared(original->eval_from_shared());
copy->set_eval_from_instructions_offset(
original->eval_from_instructions_offset());
copy->set_eval_from_position(original->eval_from_position());
// Copy all the flags, but clear compilation state.
copy->set_flags(original->flags());

View File

@ -884,7 +884,7 @@ Handle<Script> Factory::NewScript(Handle<String> source) {
script->set_wrapper(heap->undefined_value());
script->set_line_ends(heap->undefined_value());
script->set_eval_from_shared(heap->undefined_value());
script->set_eval_from_instructions_offset(0);
script->set_eval_from_position(0);
script->set_shared_function_infos(Smi::FromInt(0));
script->set_flags(0);

View File

@ -977,6 +977,12 @@ FrameSummary::FrameSummary(Object* receiver, JSFunction* function,
CannotDeoptFromAsmCode(Code::cast(abstract_code), function));
}
FrameSummary FrameSummary::GetFirst(JavaScriptFrame* frame) {
List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
frame->Summarize(&frames);
return frames.first();
}
void FrameSummary::Print() {
PrintF("receiver: ");
receiver_->ShortPrint();
@ -1228,15 +1234,15 @@ void InterpretedFrame::PatchBytecodeOffset(int new_offset) {
SetExpression(index, Smi::FromInt(raw_offset));
}
Object* InterpretedFrame::GetBytecodeArray() const {
BytecodeArray* InterpretedFrame::GetBytecodeArray() const {
const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
DCHECK_EQ(
InterpreterFrameConstants::kBytecodeArrayFromFp,
InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
return GetExpression(index);
return BytecodeArray::cast(GetExpression(index));
}
void InterpretedFrame::PatchBytecodeArray(Object* bytecode_array) {
void InterpretedFrame::PatchBytecodeArray(BytecodeArray* bytecode_array) {
const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
DCHECK_EQ(
InterpreterFrameConstants::kBytecodeArrayFromFp,

View File

@ -640,12 +640,16 @@ class ExitFrame: public StackFrame {
friend class StackFrameIteratorBase;
};
class JavaScriptFrame;
class FrameSummary BASE_EMBEDDED {
public:
FrameSummary(Object* receiver, JSFunction* function,
AbstractCode* abstract_code, int code_offset,
bool is_constructor);
static FrameSummary GetFirst(JavaScriptFrame* frame);
Handle<Object> receiver() { return receiver_; }
Handle<JSFunction> function() { return function_; }
Handle<AbstractCode> abstract_code() { return abstract_code_; }
@ -729,7 +733,6 @@ class StandardFrame : public StackFrame {
friend class SafeStackFrameIterator;
};
class JavaScriptFrame : public StandardFrame {
public:
Type type() const override { return JAVA_SCRIPT; }
@ -897,11 +900,11 @@ class InterpretedFrame : public JavaScriptFrame {
void PatchBytecodeOffset(int new_offset);
// Returns the frame's current bytecode array.
Object* GetBytecodeArray() const;
BytecodeArray* GetBytecodeArray() const;
// Updates the frame's BytecodeArray with |bytecode_array|. Used by the
// debugger to swap execution onto a BytecodeArray patched with breakpoints.
void PatchBytecodeArray(Object* bytecode_array);
void PatchBytecodeArray(BytecodeArray* bytecode_array);
// Access to the interpreter register file for this frame.
Object* GetInterpreterRegister(int register_index) const;

View File

@ -2562,8 +2562,8 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
context()->DropAndPlug(1, r0);
}
void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
int arg_count = expr->arguments()->length();
// r4: copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ ldr(r4, MemOperand(sp, arg_count * kPointerSize));
@ -2580,8 +2580,11 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
// r1: the start position of the scope the calls resides in.
__ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
// r0: the source position of the eval call.
__ mov(r0, Operand(Smi::FromInt(expr->position())));
// Do the runtime call.
__ Push(r4, r3, r2, r1);
__ Push(r4, r3, r2, r1, r0);
__ CallRuntime(Runtime::kResolvePossiblyDirectEval);
}
@ -2630,7 +2633,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call
// RuntimeHidden_asResolvePossiblyDirectEval to resolve the function we need
// Runtime_ResolvePossiblyDirectEval to resolve the function we need
// to call. Then we call the resolved function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
@ -2646,7 +2649,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// resolve eval.
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(r1);
EmitResolvePossiblyDirectEval(arg_count);
EmitResolvePossiblyDirectEval(expr);
// Touch up the stack with the resolved function.
__ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));

View File

@ -2462,8 +2462,8 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
context()->DropAndPlug(1, x0);
}
void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
int arg_count = expr->arguments()->length();
ASM_LOCATION("FullCodeGenerator::EmitResolvePossiblyDirectEval");
// Prepare to push a copy of the first argument or undefined if it doesn't
// exist.
@ -2479,9 +2479,11 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
__ Mov(x11, Smi::FromInt(language_mode()));
// Prepare to push the start position of the scope the calls resides in.
__ Mov(x12, Smi::FromInt(scope()->start_position()));
// Prepare to push the source position of the eval call.
__ Mov(x13, Smi::FromInt(expr->position()));
// Push.
__ Push(x9, x10, x11, x12);
__ Push(x9, x10, x11, x12, x13);
// Do the runtime call.
__ CallRuntime(Runtime::kResolvePossiblyDirectEval);
@ -2531,7 +2533,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
ASM_LOCATION("FullCodeGenerator::EmitPossiblyEvalCall");
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
@ -2548,7 +2550,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// resolve eval.
__ Peek(x10, (arg_count + 1) * kPointerSize);
__ Push(x10);
EmitResolvePossiblyDirectEval(arg_count);
EmitResolvePossiblyDirectEval(expr);
// Touch up the stack with the resolved function.
__ Poke(x0, (arg_count + 1) * kPointerSize);

View File

@ -552,7 +552,7 @@ class FullCodeGenerator: public AstVisitor {
bool NeedsHoleCheckForLoad(VariableProxy* proxy);
// Expects the arguments and the function already pushed.
void EmitResolvePossiblyDirectEval(int arg_count);
void EmitResolvePossiblyDirectEval(Call* expr);
// Platform-specific support for allocating a new closure based on
// the given function info.

View File

@ -2461,8 +2461,8 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
context()->DropAndPlug(1, eax);
}
void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
int arg_count = expr->arguments()->length();
// Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ push(Operand(esp, arg_count * kPointerSize));
@ -2479,6 +2479,9 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
// Push the start position of the scope the calls resides in.
__ push(Immediate(Smi::FromInt(scope()->start_position())));
// Push the source position of the eval call.
__ push(Immediate(Smi::FromInt(expr->position())));
// Do the runtime call.
__ CallRuntime(Runtime::kResolvePossiblyDirectEval);
}
@ -2525,7 +2528,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
@ -2541,7 +2544,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(arg_count);
EmitResolvePossiblyDirectEval(expr);
// Touch up the stack with the resolved function.
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);

View File

@ -2568,26 +2568,29 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
context()->DropAndPlug(1, v0);
}
void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
// t3: copy of the first argument or undefined if it doesn't exist.
void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
int arg_count = expr->arguments()->length();
// t4: copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ lw(t3, MemOperand(sp, arg_count * kPointerSize));
__ lw(t4, MemOperand(sp, arg_count * kPointerSize));
} else {
__ LoadRoot(t3, Heap::kUndefinedValueRootIndex);
__ LoadRoot(t4, Heap::kUndefinedValueRootIndex);
}
// t2: the receiver of the enclosing function.
__ lw(t2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
// t3: the receiver of the enclosing function.
__ lw(t3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
// t1: the language mode.
__ li(t1, Operand(Smi::FromInt(language_mode())));
// t2: the language mode.
__ li(t2, Operand(Smi::FromInt(language_mode())));
// t0: the start position of the scope the calls resides in.
__ li(t0, Operand(Smi::FromInt(scope()->start_position())));
// t1: the start position of the scope the calls resides in.
__ li(t1, Operand(Smi::FromInt(scope()->start_position())));
// t0: the source position of the eval call.
__ li(t0, Operand(Smi::FromInt(expr->position())));
// Do the runtime call.
__ Push(t3, t2, t1, t0);
__ Push(t4, t3, t2, t1, t0);
__ CallRuntime(Runtime::kResolvePossiblyDirectEval);
}
@ -2636,7 +2639,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
@ -2652,7 +2655,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// resolve eval.
__ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(a1);
EmitResolvePossiblyDirectEval(arg_count);
EmitResolvePossiblyDirectEval(expr);
// Touch up the stack with the resolved function.
__ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));

View File

@ -2567,8 +2567,8 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
context()->DropAndPlug(1, v0);
}
void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
int arg_count = expr->arguments()->length();
// a6: copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ ld(a6, MemOperand(sp, arg_count * kPointerSize));
@ -2585,8 +2585,11 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
// a1: the start position of the scope the calls resides in.
__ li(a1, Operand(Smi::FromInt(scope()->start_position())));
// a0: the source position of the eval call.
__ li(a0, Operand(Smi::FromInt(expr->position())));
// Do the runtime call.
__ Push(a6, a5, a4, a1);
__ Push(a6, a5, a4, a1, a0);
__ CallRuntime(Runtime::kResolvePossiblyDirectEval);
}
@ -2635,7 +2638,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
@ -2651,7 +2654,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// resolve eval.
__ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(a1);
EmitResolvePossiblyDirectEval(arg_count);
EmitResolvePossiblyDirectEval(expr);
// Touch up the stack with the resolved function.
__ sd(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));

View File

@ -2579,7 +2579,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// resolve eval.
__ LoadP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
__ push(r3);
EmitResolvePossiblyDirectEval(arg_count);
EmitResolvePossiblyDirectEval(expr);
// Touch up the stack with the resolved function.
__ StoreP(r2, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);

View File

@ -2450,8 +2450,8 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
context()->DropAndPlug(1, rax);
}
void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
int arg_count = expr->arguments()->length();
// Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ Push(Operand(rsp, arg_count * kPointerSize));
@ -2468,6 +2468,9 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
// Push the start position of the scope the calls resides in.
__ Push(Smi::FromInt(scope()->start_position()));
// Push the source position of the eval call.
__ Push(Smi::FromInt(expr->position()));
// Do the runtime call.
__ CallRuntime(Runtime::kResolvePossiblyDirectEval);
}
@ -2515,7 +2518,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
@ -2530,7 +2533,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// Push a copy of the function (found below the arguments) and resolve
// eval.
__ Push(Operand(rsp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(arg_count);
EmitResolvePossiblyDirectEval(expr);
// Touch up the callee.
__ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);

View File

@ -2453,8 +2453,8 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
context()->DropAndPlug(1, eax);
}
void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
int arg_count = expr->arguments()->length();
// Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ push(Operand(esp, arg_count * kPointerSize));
@ -2471,6 +2471,9 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
// Push the start position of the scope the calls resides in.
__ push(Immediate(Smi::FromInt(scope()->start_position())));
// Push the source position of the eval call.
__ push(Immediate(Smi::FromInt(expr->position())));
// Do the runtime call.
__ CallRuntime(Runtime::kResolvePossiblyDirectEval);
}
@ -2517,7 +2520,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
@ -2533,7 +2536,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(arg_count);
EmitResolvePossiblyDirectEval(expr);
// Touch up the stack with the resolved function.
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);

View File

@ -766,10 +766,10 @@ void Heap::PreprocessStackTraces() {
// If GC happens while adding a stack trace to the weak fixed array,
// which has been copied into a larger backing store, we may run into
// a stack trace that has already been preprocessed. Guard against this.
if (!maybe_code->IsCode()) break;
Code* code = Code::cast(maybe_code);
if (!maybe_code->IsAbstractCode()) break;
AbstractCode* abstract_code = AbstractCode::cast(maybe_code);
int offset = Smi::cast(elements->get(j + 3))->value();
int pos = code->SourcePosition(offset);
int pos = abstract_code->SourcePosition(offset);
elements->set(j + 2, Smi::FromInt(pos));
}
}

View File

@ -2457,12 +2457,14 @@ void BytecodeGenerator::VisitCall(Call* expr) {
// callee value.
if (call_type == Call::POSSIBLY_EVAL_CALL && args->length() > 0) {
RegisterAllocationScope inner_register_scope(this);
register_allocator()->PrepareForConsecutiveAllocations(5);
register_allocator()->PrepareForConsecutiveAllocations(6);
Register callee_for_eval = register_allocator()->NextConsecutiveRegister();
Register source = register_allocator()->NextConsecutiveRegister();
Register function = register_allocator()->NextConsecutiveRegister();
Register language = register_allocator()->NextConsecutiveRegister();
Register position = register_allocator()->NextConsecutiveRegister();
Register eval_scope_position =
register_allocator()->NextConsecutiveRegister();
Register eval_position = register_allocator()->NextConsecutiveRegister();
// Set up arguments for ResolvePossiblyDirectEval by copying callee, source
// strings and function closure, and loading language and
@ -2475,11 +2477,13 @@ void BytecodeGenerator::VisitCall(Call* expr) {
.StoreAccumulatorInRegister(language)
.LoadLiteral(
Smi::FromInt(execution_context()->scope()->start_position()))
.StoreAccumulatorInRegister(position);
.StoreAccumulatorInRegister(eval_scope_position)
.LoadLiteral(Smi::FromInt(expr->position()))
.StoreAccumulatorInRegister(eval_position);
// Call ResolvePossiblyDirectEval and modify the callee.
builder()
->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 5)
->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 6)
.StoreAccumulatorInRegister(callee);
}

View File

@ -5509,8 +5509,7 @@ ACCESSORS(Script, wrapper, HeapObject, kWrapperOffset)
SMI_ACCESSORS(Script, type, kTypeOffset)
ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
SMI_ACCESSORS(Script, eval_from_instructions_offset,
kEvalFrominstructionsOffsetOffset)
SMI_ACCESSORS(Script, eval_from_position, kEvalFromPositionOffset)
ACCESSORS(Script, shared_function_infos, Object, kSharedFunctionInfosOffset)
SMI_ACCESSORS(Script, flags, kFlagsOffset)
ACCESSORS(Script, source_url, Object, kSourceUrlOffset)

View File

@ -1144,8 +1144,7 @@ void Script::ScriptPrint(std::ostream& os) { // NOLINT
os << "\n - compilation type: " << compilation_type();
os << "\n - line ends: " << Brief(line_ends());
os << "\n - eval from shared: " << Brief(eval_from_shared());
os << "\n - eval from instructions offset: "
<< eval_from_instructions_offset();
os << "\n - eval from position: " << eval_from_position();
os << "\n - shared function infos: " << Brief(shared_function_infos());
os << "\n";
}

View File

@ -6436,9 +6436,9 @@ class Script: public Struct {
// function from which eval was called.
DECL_ACCESSORS(eval_from_shared, Object)
// [eval_from_instructions_offset]: the instruction offset in the code for the
// function from which eval was called where eval was called.
DECL_INT_ACCESSORS(eval_from_instructions_offset)
// [eval_from_position]: the source position in the code for the
// function from which eval was called.
DECL_INT_ACCESSORS(eval_from_position)
// [shared_function_infos]: weak fixed array containing all shared
// function infos created from this script.
@ -6525,10 +6525,10 @@ class Script: public Struct {
static const int kLineEndsOffset = kTypeOffset + kPointerSize;
static const int kIdOffset = kLineEndsOffset + kPointerSize;
static const int kEvalFromSharedOffset = kIdOffset + kPointerSize;
static const int kEvalFrominstructionsOffsetOffset =
static const int kEvalFromPositionOffset =
kEvalFromSharedOffset + kPointerSize;
static const int kSharedFunctionInfosOffset =
kEvalFrominstructionsOffsetOffset + kPointerSize;
kEvalFromPositionOffset + kPointerSize;
static const int kFlagsOffset = kSharedFunctionInfosOffset + kPointerSize;
static const int kSourceUrlOffset = kFlagsOffset + kPointerSize;
static const int kSourceMappingUrlOffset = kSourceUrlOffset + kPointerSize;

View File

@ -305,11 +305,10 @@ bool CodeGenerationFromStringsAllowed(Isolate* isolate,
}
}
static Object* CompileGlobalEval(Isolate* isolate, Handle<String> source,
Handle<SharedFunctionInfo> outer_info,
LanguageMode language_mode,
int scope_position) {
int eval_scope_position, int eval_position) {
Handle<Context> context = Handle<Context>(isolate->context());
Handle<Context> native_context = Handle<Context>(context->native_context());
@ -331,9 +330,9 @@ static Object* CompileGlobalEval(Isolate* isolate, Handle<String> source,
static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
Handle<JSFunction> compiled;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, compiled,
Compiler::GetFunctionFromEval(source, outer_info, context, language_mode,
restriction, scope_position),
isolate, compiled, Compiler::GetFunctionFromEval(
source, outer_info, context, language_mode,
restriction, eval_scope_position, eval_position),
isolate->heap()->exception());
return *compiled;
}
@ -341,7 +340,7 @@ static Object* CompileGlobalEval(Isolate* isolate, Handle<String> source,
RUNTIME_FUNCTION(Runtime_ResolvePossiblyDirectEval) {
HandleScope scope(isolate);
DCHECK(args.length() == 5);
DCHECK(args.length() == 6);
Handle<Object> callee = args.at<Object>(0);
@ -362,7 +361,7 @@ RUNTIME_FUNCTION(Runtime_ResolvePossiblyDirectEval) {
Handle<SharedFunctionInfo> outer_info(args.at<JSFunction>(2)->shared(),
isolate);
return CompileGlobalEval(isolate, args.at<String>(1), outer_info,
language_mode, args.smi_at(4));
language_mode, args.smi_at(4), args.smi_at(5));
}
} // namespace internal
} // namespace v8

View File

@ -121,7 +121,6 @@ namespace internal {
F(GetWeakSetValues, 2, 1) \
F(ObservationWeakMapCreate, 0, 1)
#define FOR_EACH_INTRINSIC_COMPILER(F) \
F(CompileLazy, 1, 1) \
F(CompileOptimized_Concurrent, 1, 1) \
@ -130,8 +129,7 @@ namespace internal {
F(NotifyDeoptimized, 1, 1) \
F(CompileForOnStackReplacement, 1, 1) \
F(TryInstallOptimizedCode, 1, 1) \
F(ResolvePossiblyDirectEval, 5, 1)
F(ResolvePossiblyDirectEval, 6, 1)
#define FOR_EACH_INTRINSIC_DATE(F) \
F(IsDate, 1, 1) \

View File

@ -11,9 +11,9 @@ wrap: yes
snippet: "
g = function(){}; eval(''); return g();
"
frame size: 9
frame size: 10
parameter count: 1
bytecode array length: 85
bytecode array length: 89
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(0),
@ -38,7 +38,9 @@ bytecodes: [
B(Star), R(7),
B(LdaSmi), U8(30),
B(Star), R(8),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(5),
B(LdaSmi), U8(52),
B(Star), R(9),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6),
B(Star), R(1),
B(Call), R(1), R(2), U8(2), U8(0),
B(LdaConstant), U8(1),

View File

@ -11,9 +11,9 @@ wrap: yes
snippet: "
return eval('1;');
"
frame size: 9
frame size: 10
parameter count: 1
bytecode array length: 65
bytecode array length: 69
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(0),
@ -36,7 +36,9 @@ bytecodes: [
B(Star), R(7),
B(LdaSmi), U8(30),
B(Star), R(8),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(5),
B(LdaSmi), U8(41),
B(Star), R(9),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6),
B(Star), R(1),
B(Call), R(1), R(2), U8(2), U8(0),
B(Return),

View File

@ -11,9 +11,9 @@ wrap: yes
snippet: "
eval('var x = 10;'); return x;
"
frame size: 9
frame size: 10
parameter count: 1
bytecode array length: 67
bytecode array length: 71
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(0),
@ -36,7 +36,9 @@ bytecodes: [
B(Star), R(7),
B(LdaSmi), U8(30),
B(Star), R(8),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(5),
B(LdaSmi), U8(34),
B(Star), R(9),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6),
B(Star), R(1),
B(Call), R(1), R(2), U8(2), U8(0),
B(LdaLookupSlot), U8(2),
@ -54,9 +56,9 @@ handlers: [
snippet: "
eval('var x = 10;'); return typeof x;
"
frame size: 9
frame size: 10
parameter count: 1
bytecode array length: 68
bytecode array length: 72
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(0),
@ -79,7 +81,9 @@ bytecodes: [
B(Star), R(7),
B(LdaSmi), U8(30),
B(Star), R(8),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(5),
B(LdaSmi), U8(34),
B(Star), R(9),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6),
B(Star), R(1),
B(Call), R(1), R(2), U8(2), U8(0),
B(LdaLookupSlotInsideTypeof), U8(2),
@ -98,9 +102,9 @@ handlers: [
snippet: "
x = 20; return eval('');
"
frame size: 9
frame size: 10
parameter count: 1
bytecode array length: 69
bytecode array length: 73
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(0),
@ -125,7 +129,9 @@ bytecodes: [
B(Star), R(7),
B(LdaSmi), U8(30),
B(Star), R(8),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(5),
B(LdaSmi), U8(49),
B(Star), R(9),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6),
B(Star), R(1),
B(Call), R(1), R(2), U8(2), U8(0),
B(Return),

View File

@ -0,0 +1,39 @@
// 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.
// Flags: --nostress-opt
Error.prepareStackTrace = function(exception, frames) {
return frames[0].getEvalOrigin();
}
var source = "new Error()";
var eval_origin;
var geval = eval;
var log = [];
(function() {
log.push([geval(source).stack, "17:13"]);
log.push([geval(source).stack, "18:13"]);
// log.push([geval(source).stack, "19:13"]); TODO(4921).
})();
(function() {
log.push([eval(source).stack, "23:13"]);
log.push([eval(source).stack, "24:13"]);
// log.push([eval(source).stack, "25:13"]); TODO(4921).
})();
log.push([eval(source).stack, "28:11"]);
log.push([eval(source).stack, "29:11"]);
// log.push([eval(source).stack, "30:11"]); TODO(4921).
Error.prepareStackTrace = undefined;
for (var item of log) {
var stacktraceline = item[0];
var expectation = item[1];
var re = new RegExp(`:${expectation}\\)$`);
assertTrue(re.test(stacktraceline));
}