Commit c7393ac8 authored by Junliang Yan's avatar Junliang Yan Committed by Commit Bot

PPC/s390: interpreter: make interpreted frames distinguishable in the native stack

Port ada64b58

Original Commit Message:

    Before Turbofan/Ignition it was possible to use external profilers to
    sample running V8/Node.js processes and generate reports/FlameGraphs
    from that. It's still possible to do so, but non-optimized JavaScript
    functions appear in the stack as InterpreterEntryTrampoline. This commit
    adds a runtime flag which makes interpreted frames visible on the
    process' native stack as distinguishable functions, making the sampled
    data gathered by external profilers such as Linux perf and DTrace more
    useful.

R=matheus@sthima.com.br, joransiu@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=
LOG=N

Change-Id: I0416b53c53248a5624061d0155712a3e2396c725
Reviewed-on: https://chromium-review.googlesource.com/1008045Reviewed-by: 's avatarJoran Siu <joransiu@ca.ibm.com>
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#52551}
parent 638c9507
......@@ -452,6 +452,18 @@ void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
Generate_JSBuiltinsConstructStubHelper(masm);
}
static void GetSharedFunctionInfoBytecode(MacroAssembler* masm,
Register sfi_data,
Register scratch1) {
Label done;
__ CompareObjectType(sfi_data, scratch1, scratch1, INTERPRETER_DATA_TYPE);
__ bne(&done);
__ LoadP(sfi_data,
FieldMemOperand(sfi_data, InterpreterData::kBytecodeArrayOffset));
__ bind(&done);
}
// static
void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
// ----------- S t a t e -------------
......@@ -532,7 +544,9 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
// Underlying function needs to have bytecode available.
if (FLAG_debug_code) {
__ LoadP(r6, FieldMemOperand(r7, JSFunction::kSharedFunctionInfoOffset));
__ LoadP(r6, FieldMemOperand(r6, SharedFunctionInfo::kFunctionDataOffset));
GetSharedFunctionInfoBytecode(masm, r6, r3);
__ CompareObjectType(r6, r6, r6, BYTECODE_ARRAY_TYPE);
__ Assert(eq, AbortReason::kMissingBytecodeArray);
}
......@@ -921,6 +935,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// Load original bytecode array or the debug copy.
__ LoadP(kInterpreterBytecodeArrayRegister,
FieldMemOperand(r3, SharedFunctionInfo::kFunctionDataOffset));
GetSharedFunctionInfoBytecode(masm, kInterpreterBytecodeArrayRegister, r7);
__ LoadP(r7, FieldMemOperand(r3, SharedFunctionInfo::kDebugInfoOffset));
__ TestIfSmi(r7, r0);
__ bne(&maybe_load_debug_bytecode_array, cr0);
......@@ -1214,10 +1229,29 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
static void Generate_InterpreterEnterBytecode(MacroAssembler* masm) {
// Set the return address to the correct point in the interpreter entry
// trampoline.
Label builtin_trampoline, trampoline_loaded;
Smi* interpreter_entry_return_pc_offset(
masm->isolate()->heap()->interpreter_entry_return_pc_offset());
DCHECK_NE(interpreter_entry_return_pc_offset, Smi::kZero);
// If the SFI function_data is an InterpreterData, get the trampoline stored
// in it, otherwise get the trampoline from the builtins list.
__ LoadP(r5, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
__ LoadP(r5, FieldMemOperand(r5, JSFunction::kSharedFunctionInfoOffset));
__ LoadP(r5, FieldMemOperand(r5, SharedFunctionInfo::kFunctionDataOffset));
__ CompareObjectType(r5, kInterpreterDispatchTableRegister,
kInterpreterDispatchTableRegister,
INTERPRETER_DATA_TYPE);
__ bne(&builtin_trampoline);
__ LoadP(r5,
FieldMemOperand(r5, InterpreterData::kInterpreterTrampolineOffset));
__ b(&trampoline_loaded);
__ bind(&builtin_trampoline);
__ Move(r5, BUILTIN_CODE(masm->isolate(), InterpreterEntryTrampoline));
__ bind(&trampoline_loaded);
__ addi(r0, r5, Operand(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
__ mtlr(r0);
......@@ -1310,6 +1344,7 @@ static void GetSharedFunctionInfoCode(MacroAssembler* masm, Register sfi_data,
Label check_is_fixed_array;
Label check_is_pre_parsed_scope_data;
Label check_is_function_template_info;
Label check_is_interpreter_data;
Register data_type = scratch1;
......@@ -1354,11 +1389,21 @@ static void GetSharedFunctionInfoCode(MacroAssembler* masm, Register sfi_data,
// IsFunctionTemplateInfo: API call
__ bind(&check_is_function_template_info);
__ cmpi(data_type, Operand(FUNCTION_TEMPLATE_INFO_TYPE));
__ bne(&check_is_interpreter_data);
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
__ b(&done);
// IsInterpreterData: Interpret bytecode
__ bind(&check_is_interpreter_data);
if (FLAG_debug_code) {
__ cmpi(data_type, Operand(FUNCTION_TEMPLATE_INFO_TYPE));
__ cmpi(data_type, Operand(INTERPRETER_DATA_TYPE));
__ Assert(eq, AbortReason::kInvalidSharedFunctionInfoData);
}
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
__ LoadP(
sfi_data,
FieldMemOperand(sfi_data, InterpreterData::kInterpreterTrampolineOffset));
__ bind(&done);
}
......
......@@ -450,6 +450,18 @@ void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
Generate_JSBuiltinsConstructStubHelper(masm);
}
static void GetSharedFunctionInfoBytecode(MacroAssembler* masm,
Register sfi_data,
Register scratch1) {
Label done;
__ CompareObjectType(sfi_data, scratch1, scratch1, INTERPRETER_DATA_TYPE);
__ bne(&done, Label::kNear);
__ LoadP(sfi_data,
FieldMemOperand(sfi_data, InterpreterData::kBytecodeArrayOffset));
__ bind(&done);
}
// static
void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
// ----------- S t a t e -------------
......@@ -534,7 +546,9 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
// Underlying function needs to have bytecode available.
if (FLAG_debug_code) {
__ LoadP(r5, FieldMemOperand(r6, JSFunction::kSharedFunctionInfoOffset));
__ LoadP(r5, FieldMemOperand(r5, SharedFunctionInfo::kFunctionDataOffset));
GetSharedFunctionInfoBytecode(masm, r5, r1);
__ CompareObjectType(r5, r5, r5, BYTECODE_ARRAY_TYPE);
__ Assert(eq, AbortReason::kMissingBytecodeArray);
}
......@@ -932,6 +946,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// Load original bytecode array or the debug copy.
__ LoadP(kInterpreterBytecodeArrayRegister,
FieldMemOperand(r2, SharedFunctionInfo::kFunctionDataOffset));
GetSharedFunctionInfoBytecode(masm, kInterpreterBytecodeArrayRegister, r6);
__ LoadP(r6, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset));
__ TestIfSmi(r6);
__ bne(&maybe_load_debug_bytecode_array);
......@@ -1220,10 +1235,29 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
static void Generate_InterpreterEnterBytecode(MacroAssembler* masm) {
// Set the return address to the correct point in the interpreter entry
// trampoline.
Label builtin_trampoline, trampoline_loaded;
Smi* interpreter_entry_return_pc_offset(
masm->isolate()->heap()->interpreter_entry_return_pc_offset());
DCHECK_NE(interpreter_entry_return_pc_offset, Smi::kZero);
// If the SFI function_data is an InterpreterData, get the trampoline stored
// in it, otherwise get the trampoline from the builtins list.
__ LoadP(r4, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
__ LoadP(r4, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
__ LoadP(r4, FieldMemOperand(r4, SharedFunctionInfo::kFunctionDataOffset));
__ CompareObjectType(r4, kInterpreterDispatchTableRegister,
kInterpreterDispatchTableRegister,
INTERPRETER_DATA_TYPE);
__ bne(&builtin_trampoline);
__ LoadP(r4,
FieldMemOperand(r4, InterpreterData::kInterpreterTrampolineOffset));
__ b(&trampoline_loaded);
__ bind(&builtin_trampoline);
__ Move(r4, BUILTIN_CODE(masm->isolate(), InterpreterEntryTrampoline));
__ bind(&trampoline_loaded);
__ AddP(r14, r4, Operand(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
......@@ -1314,6 +1348,7 @@ static void GetSharedFunctionInfoCode(MacroAssembler* masm, Register sfi_data,
Label check_is_fixed_array;
Label check_is_pre_parsed_scope_data;
Label check_is_function_template_info;
Label check_is_interpreter_data;
Register data_type = scratch1;
......@@ -1358,11 +1393,21 @@ static void GetSharedFunctionInfoCode(MacroAssembler* masm, Register sfi_data,
// IsFunctionTemplateInfo: API call
__ bind(&check_is_function_template_info);
__ CmpP(data_type, Operand(FUNCTION_TEMPLATE_INFO_TYPE));
__ bne(&check_is_interpreter_data);
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
__ b(&done);
// IsInterpreterData: Interpret bytecode
__ bind(&check_is_interpreter_data);
if (FLAG_debug_code) {
__ CmpP(data_type, Operand(FUNCTION_TEMPLATE_INFO_TYPE));
__ CmpP(data_type, Operand(INTERPRETER_DATA_TYPE));
__ Assert(eq, AbortReason::kInvalidSharedFunctionInfoData);
}
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
__ LoadP(
sfi_data,
FieldMemOperand(sfi_data, InterpreterData::kInterpreterTrampolineOffset));
__ bind(&done);
}
......
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