interpreter: make interpreted frames distinguishable in the native stack

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=bmeurer@google.com, franzih@google.com, jarin@google.com, yangguo@google.com

Bug: v8:7155
Change-Id: I3dc8876aa3cd9f1b9766624842a7cc354ccca415
Reviewed-on: https://chromium-review.googlesource.com/959081
Commit-Queue: Yang Guo <yangguo@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52533}
This commit is contained in:
Matheus Marchini 2018-04-10 11:31:06 -03:00 committed by Commit Bot
parent 4b0644f501
commit ada64b58bf
46 changed files with 706 additions and 218 deletions

View File

@ -98,6 +98,7 @@ Maciej Małecki <me@mmalecki.com>
Marcin Cieślak <saper@marcincieslak.com>
Marcin Wiącek <marcin@mwiacek.com>
Mateusz Czeladka <mateusz.szczap@gmail.com>
Matheus Marchini <matheus@sthima.com.br>
Mathias Bynens <mathias@qiwi.be>
Matt Hanselman <mjhanselman@gmail.com>
Matthew Sporleder <msporleder@gmail.com>

View File

@ -445,6 +445,19 @@ 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);
__ b(ne, &done);
__ ldr(sfi_data,
FieldMemOperand(sfi_data, InterpreterData::kBytecodeArrayOffset));
__ bind(&done);
}
// static
void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -524,6 +537,7 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ ldr(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
__ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kFunctionDataOffset));
GetSharedFunctionInfoBytecode(masm, r3, r0);
__ CompareObjectType(r3, r3, r3, BYTECODE_ARRAY_TYPE);
__ Assert(eq, AbortReason::kMissingBytecodeArray);
}
@ -915,6 +929,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ ldr(r0, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
__ ldr(kInterpreterBytecodeArrayRegister,
FieldMemOperand(r0, SharedFunctionInfo::kFunctionDataOffset));
GetSharedFunctionInfoBytecode(masm, kInterpreterBytecodeArrayRegister, r4);
__ ldr(r4, FieldMemOperand(r0, SharedFunctionInfo::kDebugInfoOffset));
__ SmiTst(r4);
__ b(ne, &maybe_load_debug_bytecode_array);
@ -1185,10 +1200,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.
__ ldr(r2, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
__ ldr(r2, FieldMemOperand(r2, JSFunction::kSharedFunctionInfoOffset));
__ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kFunctionDataOffset));
__ CompareObjectType(r2, kInterpreterDispatchTableRegister,
kInterpreterDispatchTableRegister,
INTERPRETER_DATA_TYPE);
__ b(ne, &builtin_trampoline);
__ ldr(r2,
FieldMemOperand(r2, InterpreterData::kInterpreterTrampolineOffset));
__ b(&trampoline_loaded);
__ bind(&builtin_trampoline);
__ Move(r2, BUILTIN_CODE(masm->isolate(), InterpreterEntryTrampoline));
__ bind(&trampoline_loaded);
__ add(lr, r2, Operand(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
@ -1280,6 +1314,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;
@ -1322,11 +1357,20 @@ static void GetSharedFunctionInfoCode(MacroAssembler* masm, Register sfi_data,
// IsFunctionTemplateInfo: API call
__ bind(&check_is_function_template_info);
__ cmp(data_type, Operand(FUNCTION_TEMPLATE_INFO_TYPE));
__ b(ne, &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) {
__ cmp(data_type, Operand(FUNCTION_TEMPLATE_INFO_TYPE));
__ cmp(data_type, Operand(INTERPRETER_DATA_TYPE));
__ Assert(eq, AbortReason::kInvalidSharedFunctionInfoData);
}
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
__ ldr(
sfi_data,
FieldMemOperand(sfi_data, InterpreterData::kInterpreterTrampolineOffset));
__ bind(&done);
}

View File

@ -581,8 +581,13 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
// Underlying function needs to have bytecode available.
if (FLAG_debug_code) {
Label check_has_bytecode_array;
__ Ldr(x3, FieldMemOperand(x4, JSFunction::kSharedFunctionInfoOffset));
__ Ldr(x3, FieldMemOperand(x3, SharedFunctionInfo::kFunctionDataOffset));
__ CompareObjectType(x3, x0, x0, INTERPRETER_DATA_TYPE);
__ B(ne, &check_has_bytecode_array);
__ Ldr(x3, FieldMemOperand(x3, InterpreterData::kBytecodeArrayOffset));
__ Bind(&check_has_bytecode_array);
__ CompareObjectType(x3, x3, x3, BYTECODE_ARRAY_TYPE);
__ Assert(eq, AbortReason::kMissingBytecodeArray);
}
@ -1004,10 +1009,18 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// Get the bytecode array from the function object (or from the DebugInfo if
// it is present) and load it into kInterpreterBytecodeArrayRegister.
Label maybe_load_debug_bytecode_array, bytecode_array_loaded;
Label maybe_load_debug_bytecode_array, bytecode_array_loaded,
has_bytecode_array;
__ Ldr(x0, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
__ Ldr(kInterpreterBytecodeArrayRegister,
FieldMemOperand(x0, SharedFunctionInfo::kFunctionDataOffset));
__ CompareObjectType(kInterpreterBytecodeArrayRegister, x11, x11,
INTERPRETER_DATA_TYPE);
__ B(ne, &has_bytecode_array);
__ Ldr(kInterpreterBytecodeArrayRegister,
FieldMemOperand(kInterpreterBytecodeArrayRegister,
InterpreterData::kBytecodeArrayOffset));
__ Bind(&has_bytecode_array);
__ Ldr(x11, FieldMemOperand(x0, SharedFunctionInfo::kDebugInfoOffset));
__ JumpIfNotSmi(x11, &maybe_load_debug_bytecode_array);
__ Bind(&bytecode_array_loaded);
@ -1301,10 +1314,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.
__ Ldr(x1, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
__ Ldr(x1, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
__ Ldr(x1, FieldMemOperand(x1, SharedFunctionInfo::kFunctionDataOffset));
__ CompareObjectType(x1, kInterpreterDispatchTableRegister,
kInterpreterDispatchTableRegister,
INTERPRETER_DATA_TYPE);
__ B(ne, &builtin_trampoline);
__ Ldr(x1,
FieldMemOperand(x1, InterpreterData::kInterpreterTrampolineOffset));
__ B(&trampoline_loaded);
__ Bind(&builtin_trampoline);
__ LoadObject(x1, BUILTIN_CODE(masm->isolate(), InterpreterEntryTrampoline));
__ Bind(&trampoline_loaded);
__ Add(lr, x1, Operand(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
@ -1394,6 +1426,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;
@ -1436,11 +1469,20 @@ static void GetSharedFunctionInfoCode(MacroAssembler* masm, Register sfi_data,
// IsFunctionTemplateInfo: API call
__ Bind(&check_is_function_template_info);
__ Cmp(data_type, Operand(FUNCTION_TEMPLATE_INFO_TYPE));
__ B(ne, &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) {
__ Cmp(data_type, Operand(FUNCTION_TEMPLATE_INFO_TYPE));
__ Cmp(data_type, Operand(INTERPRETER_DATA_TYPE));
__ Assert(eq, AbortReason::kInvalidSharedFunctionInfoData);
}
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
__ Ldr(
sfi_data,
FieldMemOperand(sfi_data, InterpreterData::kInterpreterTrampolineOffset));
__ Bind(&done);
}

View File

@ -1075,8 +1075,8 @@ TF_BUILTIN(CreateGeneratorObject, ObjectBuiltinsAssembler) {
Node* shared =
LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset);
Node* bytecode_array =
LoadObjectField(shared, SharedFunctionInfo::kFunctionDataOffset);
Node* bytecode_array = LoadSharedFunctionInfoBytecodeArray(shared);
Node* frame_size = ChangeInt32ToIntPtr(LoadObjectField(
bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Int32()));
Node* size = WordSar(frame_size, IntPtrConstant(kPointerSizeLog2));

View File

@ -494,6 +494,19 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
Generate_JSEntryTrampolineHelper(masm, true);
}
static void GetSharedFunctionInfoBytecode(MacroAssembler* masm,
Register sfi_data,
Register scratch1) {
Label done;
__ CmpObjectType(sfi_data, INTERPRETER_DATA_TYPE, scratch1);
__ j(not_equal, &done, Label::kNear);
__ mov(sfi_data,
FieldOperand(sfi_data, InterpreterData::kBytecodeArrayOffset));
__ bind(&done);
}
// static
void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -568,6 +581,9 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
__ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kFunctionDataOffset));
__ Push(eax);
GetSharedFunctionInfoBytecode(masm, ecx, eax);
__ Pop(eax);
__ CmpObjectType(ecx, BYTECODE_ARRAY_TYPE, ecx);
__ Assert(equal, AbortReason::kMissingBytecodeArray);
}
@ -855,6 +871,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
__ mov(kInterpreterBytecodeArrayRegister,
FieldOperand(eax, SharedFunctionInfo::kFunctionDataOffset));
__ Push(eax);
GetSharedFunctionInfoBytecode(masm, kInterpreterBytecodeArrayRegister, eax);
__ Pop(eax);
__ JumpIfNotSmi(FieldOperand(eax, SharedFunctionInfo::kDebugInfoOffset),
&maybe_load_debug_bytecode_array);
__ bind(&bytecode_array_loaded);
@ -1239,10 +1258,28 @@ 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.
__ mov(ebx, Operand(ebp, StandardFrameConstants::kFunctionOffset));
__ mov(ebx, FieldOperand(ebx, JSFunction::kSharedFunctionInfoOffset));
__ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFunctionDataOffset));
__ Push(eax);
__ CmpObjectType(ebx, INTERPRETER_DATA_TYPE, eax);
__ j(not_equal, &builtin_trampoline, Label::kNear);
__ mov(ebx, FieldOperand(ebx, InterpreterData::kInterpreterTrampolineOffset));
__ jmp(&trampoline_loaded, Label::kNear);
__ bind(&builtin_trampoline);
__ Move(ebx, BUILTIN_CODE(masm->isolate(), InterpreterEntryTrampoline));
__ bind(&trampoline_loaded);
__ Pop(eax);
__ add(ebx, Immediate(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
__ push(ebx);
@ -1333,6 +1370,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;
@ -1377,11 +1415,19 @@ static void GetSharedFunctionInfoCode(MacroAssembler* masm, Register sfi_data,
// IsFunctionTemplateInfo: API call
__ bind(&check_is_function_template_info);
__ cmpw(data_type, Immediate(FUNCTION_TEMPLATE_INFO_TYPE));
__ j(not_equal, &check_is_interpreter_data);
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
__ jmp(&done);
// IsInterpreterData: Interpret bytecode
__ bind(&check_is_interpreter_data);
if (FLAG_debug_code) {
__ cmpw(data_type, Immediate(FUNCTION_TEMPLATE_INFO_TYPE));
__ cmpw(data_type, Immediate(INTERPRETER_DATA_TYPE));
__ Check(equal, AbortReason::kInvalidSharedFunctionInfoData);
}
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
__ mov(sfi_data,
FieldOperand(sfi_data, InterpreterData::kInterpreterTrampolineOffset));
__ bind(&done);
}

View File

@ -548,6 +548,19 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
Generate_JSEntryTrampolineHelper(masm, true);
}
static void GetSharedFunctionInfoBytecode(MacroAssembler* masm,
Register sfi_data,
Register scratch1) {
Label done;
__ GetObjectType(sfi_data, scratch1, scratch1);
__ Branch(&done, ne, scratch1, Operand(INTERPRETER_DATA_TYPE));
__ lw(sfi_data,
FieldMemOperand(sfi_data, InterpreterData::kBytecodeArrayOffset));
__ bind(&done);
}
// static
void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -623,6 +636,7 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ lw(a3, FieldMemOperand(t0, JSFunction::kSharedFunctionInfoOffset));
__ lw(a3, FieldMemOperand(a3, SharedFunctionInfo::kFunctionDataOffset));
GetSharedFunctionInfoBytecode(masm, a3, a0);
__ GetObjectType(a3, a3, a3);
__ Assert(eq, AbortReason::kMissingBytecodeArray, a3,
Operand(BYTECODE_ARRAY_TYPE));
@ -899,6 +913,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ lw(a0, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
__ lw(kInterpreterBytecodeArrayRegister,
FieldMemOperand(a0, SharedFunctionInfo::kFunctionDataOffset));
GetSharedFunctionInfoBytecode(masm, kInterpreterBytecodeArrayRegister, t0);
__ lw(t0, FieldMemOperand(a0, SharedFunctionInfo::kDebugInfoOffset));
__ JumpIfNotSmi(t0, &maybe_load_debug_bytecode_array);
__ bind(&bytecode_array_loaded);
@ -1188,10 +1203,28 @@ 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.
__ lw(t0, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
__ lw(t0, FieldMemOperand(t0, JSFunction::kSharedFunctionInfoOffset));
__ lw(t0, FieldMemOperand(t0, SharedFunctionInfo::kFunctionDataOffset));
__ GetObjectType(t0, kInterpreterDispatchTableRegister,
kInterpreterDispatchTableRegister);
__ Branch(&builtin_trampoline, ne, kInterpreterDispatchTableRegister,
Operand(INTERPRETER_DATA_TYPE));
__ lw(t0, FieldMemOperand(t0, InterpreterData::kInterpreterTrampolineOffset));
__ Branch(&trampoline_loaded);
__ bind(&builtin_trampoline);
__ li(t0, Operand(BUILTIN_CODE(masm->isolate(), InterpreterEntryTrampoline)));
__ bind(&trampoline_loaded);
__ Addu(ra, t0, Operand(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
@ -1285,6 +1318,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;
@ -1329,11 +1363,18 @@ static void GetSharedFunctionInfoCode(MacroAssembler* masm, Register sfi_data,
// IsFunctionTemplateInfo: API call
__ bind(&check_is_function_template_info);
__ Branch(&check_is_interpreter_data, ne, data_type,
Operand(FUNCTION_TEMPLATE_INFO_TYPE));
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
// IsInterpreterData: Interpret bytecode
__ bind(&check_is_interpreter_data);
if (FLAG_debug_code) {
__ Assert(eq, AbortReason::kInvalidSharedFunctionInfoData, data_type,
Operand(FUNCTION_TEMPLATE_INFO_TYPE));
Operand(INTERPRETER_DATA_TYPE));
}
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
__ lw(sfi_data, FieldMemOperand(
sfi_data, InterpreterData::kInterpreterTrampolineOffset));
__ bind(&done);
}

View File

@ -438,6 +438,19 @@ void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
Generate_JSBuiltinsConstructStubHelper(masm);
}
static void GetSharedFunctionInfoBytecode(MacroAssembler* masm,
Register sfi_data,
Register scratch1) {
Label done;
__ GetObjectType(sfi_data, scratch1, scratch1);
__ Branch(&done, ne, scratch1, Operand(INTERPRETER_DATA_TYPE));
__ Ld(sfi_data,
FieldMemOperand(sfi_data, InterpreterData::kBytecodeArrayOffset));
__ bind(&done);
}
// static
void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -512,6 +525,7 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ Ld(a3, FieldMemOperand(a4, JSFunction::kSharedFunctionInfoOffset));
__ Ld(a3, FieldMemOperand(a3, SharedFunctionInfo::kFunctionDataOffset));
GetSharedFunctionInfoBytecode(masm, a3, a0);
__ GetObjectType(a3, a3, a3);
__ Assert(eq, AbortReason::kMissingBytecodeArray, a3,
Operand(BYTECODE_ARRAY_TYPE));
@ -896,6 +910,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Ld(a0, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
__ Ld(kInterpreterBytecodeArrayRegister,
FieldMemOperand(a0, SharedFunctionInfo::kFunctionDataOffset));
GetSharedFunctionInfoBytecode(masm, kInterpreterBytecodeArrayRegister, a4);
__ Ld(a4, FieldMemOperand(a0, SharedFunctionInfo::kDebugInfoOffset));
__ JumpIfNotSmi(a4, &maybe_load_debug_bytecode_array);
__ bind(&bytecode_array_loaded);
@ -1185,10 +1200,28 @@ 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.
__ Ld(t0, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
__ Ld(t0, FieldMemOperand(t0, JSFunction::kSharedFunctionInfoOffset));
__ Ld(t0, FieldMemOperand(t0, SharedFunctionInfo::kFunctionDataOffset));
__ GetObjectType(t0, kInterpreterDispatchTableRegister,
kInterpreterDispatchTableRegister);
__ Branch(&builtin_trampoline, ne, kInterpreterDispatchTableRegister,
Operand(INTERPRETER_DATA_TYPE));
__ Ld(t0, FieldMemOperand(t0, InterpreterData::kInterpreterTrampolineOffset));
__ Branch(&trampoline_loaded);
__ bind(&builtin_trampoline);
__ li(t0, Operand(BUILTIN_CODE(masm->isolate(), InterpreterEntryTrampoline)));
__ bind(&trampoline_loaded);
__ Daddu(ra, t0, Operand(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
@ -1282,6 +1315,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;
@ -1326,11 +1360,18 @@ static void GetSharedFunctionInfoCode(MacroAssembler* masm, Register sfi_data,
// IsFunctionTemplateInfo: API call
__ bind(&check_is_function_template_info);
__ Branch(&check_is_interpreter_data, ne, data_type,
Operand(FUNCTION_TEMPLATE_INFO_TYPE));
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
// IsInterpreterData: Interpret bytecode
__ bind(&check_is_interpreter_data);
if (FLAG_debug_code) {
__ Assert(eq, AbortReason::kInvalidSharedFunctionInfoData, data_type,
Operand(FUNCTION_TEMPLATE_INFO_TYPE));
Operand(INTERPRETER_DATA_TYPE));
}
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
__ Ld(sfi_data, FieldMemOperand(
sfi_data, InterpreterData::kInterpreterTrampolineOffset));
__ bind(&done);
}

View File

@ -559,6 +559,19 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
Generate_JSEntryTrampolineHelper(masm, true);
}
static void GetSharedFunctionInfoBytecode(MacroAssembler* masm,
Register sfi_data,
Register scratch1) {
Label done;
__ CmpObjectType(sfi_data, INTERPRETER_DATA_TYPE, scratch1);
__ j(not_equal, &done, Label::kNear);
__ movp(sfi_data,
FieldOperand(sfi_data, InterpreterData::kBytecodeArrayOffset));
__ bind(&done);
}
// static
void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -636,6 +649,7 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
if (FLAG_debug_code) {
__ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
__ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kFunctionDataOffset));
GetSharedFunctionInfoBytecode(masm, rcx, kScratchRegister);
__ CmpObjectType(rcx, BYTECODE_ARRAY_TYPE, rcx);
__ Assert(equal, AbortReason::kMissingBytecodeArray);
}
@ -867,7 +881,7 @@ static void AdvanceBytecodeOffsetOrReturn(MacroAssembler* masm,
#define JUMP_IF_EQUAL(NAME) \
__ cmpb(bytecode, \
Immediate(static_cast<int>(interpreter::Bytecode::k##NAME))); \
__ j(equal, if_return, Label::kNear);
__ j(equal, if_return, Label::kFar);
RETURN_BYTECODE_LIST(JUMP_IF_EQUAL)
#undef JUMP_IF_EQUAL
@ -918,6 +932,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ movp(rax, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset));
__ movp(kInterpreterBytecodeArrayRegister,
FieldOperand(rax, SharedFunctionInfo::kFunctionDataOffset));
GetSharedFunctionInfoBytecode(masm, kInterpreterBytecodeArrayRegister,
kScratchRegister);
__ JumpIfNotSmi(FieldOperand(rax, SharedFunctionInfo::kDebugInfoOffset),
&maybe_load_debug_bytecode_array);
__ bind(&bytecode_array_loaded);
@ -1214,13 +1230,30 @@ 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;
// TODO(jgruber,v8:6666): Update logic once builtin is isolate-independent.
DCHECK(
!Builtins::IsIsolateIndependent(Builtins::kInterpreterEntryTrampoline));
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.
__ movp(rbx, Operand(rbp, StandardFrameConstants::kFunctionOffset));
__ movp(rbx, FieldOperand(rbx, JSFunction::kSharedFunctionInfoOffset));
__ movp(rbx, FieldOperand(rbx, SharedFunctionInfo::kFunctionDataOffset));
__ CmpObjectType(rbx, INTERPRETER_DATA_TYPE, kScratchRegister);
__ j(not_equal, &builtin_trampoline, Label::kNear);
__ movp(rbx,
FieldOperand(rbx, InterpreterData::kInterpreterTrampolineOffset));
__ jmp(&trampoline_loaded, Label::kNear);
__ bind(&builtin_trampoline);
__ Move(rbx, BUILTIN_CODE(masm->isolate(), InterpreterEntryTrampoline));
__ bind(&trampoline_loaded);
__ addp(rbx, Immediate(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
__ Push(rbx);
@ -1315,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;
@ -1357,11 +1391,20 @@ static void GetSharedFunctionInfoCode(MacroAssembler* masm, Register sfi_data,
// IsFunctionTemplateInfo: API call
__ bind(&check_is_function_template_info);
__ cmpw(data_type, Immediate(FUNCTION_TEMPLATE_INFO_TYPE));
__ j(not_equal, &check_is_interpreter_data);
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
__ j(always, &done);
// IsInterpreterData: Interpret bytecode with unique interpreter
__ bind(&check_is_interpreter_data);
if (FLAG_debug_code) {
__ cmpw(data_type, Immediate(FUNCTION_TEMPLATE_INFO_TYPE));
__ cmpw(data_type, Immediate(INTERPRETER_DATA_TYPE));
__ Check(equal, AbortReason::kInvalidSharedFunctionInfoData);
}
__ Move(sfi_data, BUILTIN_CODE(masm->isolate(), HandleApiCall));
__ movp(
sfi_data,
FieldOperand(sfi_data, InterpreterData::kInterpreterTrampolineOffset));
__ bind(&done);
}

View File

@ -24,27 +24,28 @@ class WasmCode;
using WasmName = Vector<const char>;
} // namespace wasm
#define LOG_EVENTS_AND_TAGS_LIST(V) \
V(CODE_CREATION_EVENT, "code-creation") \
V(CODE_DISABLE_OPT_EVENT, "code-disable-optimization") \
V(CODE_MOVE_EVENT, "code-move") \
V(CODE_DELETE_EVENT, "code-delete") \
V(CODE_MOVING_GC, "code-moving-gc") \
V(SHARED_FUNC_MOVE_EVENT, "sfi-move") \
V(SNAPSHOT_CODE_NAME_EVENT, "snapshot-code-name") \
V(TICK_EVENT, "tick") \
V(BUILTIN_TAG, "Builtin") \
V(CALLBACK_TAG, "Callback") \
V(EVAL_TAG, "Eval") \
V(FUNCTION_TAG, "Function") \
V(HANDLER_TAG, "Handler") \
V(BYTECODE_HANDLER_TAG, "BytecodeHandler") \
V(LAZY_COMPILE_TAG, "LazyCompile") \
V(REG_EXP_TAG, "RegExp") \
V(SCRIPT_TAG, "Script") \
V(STUB_TAG, "Stub") \
V(NATIVE_FUNCTION_TAG, "Function") \
V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile") \
#define LOG_EVENTS_AND_TAGS_LIST(V) \
V(CODE_CREATION_EVENT, "code-creation") \
V(CODE_DISABLE_OPT_EVENT, "code-disable-optimization") \
V(CODE_MOVE_EVENT, "code-move") \
V(CODE_DELETE_EVENT, "code-delete") \
V(CODE_MOVING_GC, "code-moving-gc") \
V(SHARED_FUNC_MOVE_EVENT, "sfi-move") \
V(SNAPSHOT_CODE_NAME_EVENT, "snapshot-code-name") \
V(TICK_EVENT, "tick") \
V(BUILTIN_TAG, "Builtin") \
V(CALLBACK_TAG, "Callback") \
V(EVAL_TAG, "Eval") \
V(FUNCTION_TAG, "Function") \
V(INTERPRETED_FUNCTION_TAG, "InterpretedFunction") \
V(HANDLER_TAG, "Handler") \
V(BYTECODE_HANDLER_TAG, "BytecodeHandler") \
V(LAZY_COMPILE_TAG, "LazyCompile") \
V(REG_EXP_TAG, "RegExp") \
V(SCRIPT_TAG, "Script") \
V(STUB_TAG, "Stub") \
V(NATIVE_FUNCTION_TAG, "Function") \
V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile") \
V(NATIVE_SCRIPT_TAG, "Script")
// Note that 'NATIVE_' cases for functions and scripts are mapped onto
// original tags when writing to the log.

View File

@ -2110,6 +2110,26 @@ Node* CodeStubAssembler::LoadJSFunctionPrototype(Node* function,
return var_result.value();
}
Node* CodeStubAssembler::LoadSharedFunctionInfoBytecodeArray(Node* shared) {
CSA_ASSERT(this, TaggedIsNotSmi(shared));
CSA_ASSERT(this, IsSharedFunctionInfo(shared));
Node* function_data =
LoadObjectField(shared, SharedFunctionInfo::kFunctionDataOffset);
VARIABLE(var_result, MachineRepresentation::kTagged, function_data);
Label done(this, &var_result);
GotoIfNot(HasInstanceType(function_data, INTERPRETER_DATA_TYPE), &done);
Node* bytecode_array =
LoadObjectField(function_data, InterpreterData::kBytecodeArrayOffset);
var_result.Bind(bytecode_array);
Goto(&done);
BIND(&done);
return var_result.value();
}
void CodeStubAssembler::StoreHeapNumberValue(SloppyTNode<HeapNumber> object,
SloppyTNode<Float64T> value) {
StoreObjectFieldNoWriteBarrier(object, HeapNumber::kValueOffset, value,
@ -11024,17 +11044,18 @@ TNode<Code> CodeStubAssembler::GetSharedFunctionInfoCode(
TNode<Int32T> data_type = LoadInstanceType(CAST(sfi_data));
int32_t case_values[] = {BYTECODE_ARRAY_TYPE, CODE_TYPE, FIXED_ARRAY_TYPE,
TUPLE2_TYPE};
TUPLE2_TYPE, FUNCTION_TEMPLATE_INFO_TYPE};
Label check_is_bytecode_array(this);
Label check_is_code(this);
Label check_is_fixed_array(this);
Label check_is_pre_parsed_scope_data(this);
Label check_is_function_template_info(this);
Label* case_labels[] = {&check_is_bytecode_array, &check_is_code,
&check_is_fixed_array,
&check_is_pre_parsed_scope_data};
Label check_is_interpreter_data(this);
Label* case_labels[] = {
&check_is_bytecode_array, &check_is_code, &check_is_fixed_array,
&check_is_pre_parsed_scope_data, &check_is_function_template_info};
STATIC_ASSERT(arraysize(case_values) == arraysize(case_labels));
Switch(data_type, &check_is_function_template_info, case_values, case_labels,
Switch(data_type, &check_is_interpreter_data, case_values, case_labels,
arraysize(case_labels));
// IsBytecodeArray: Interpret bytecode
@ -11062,13 +11083,19 @@ TNode<Code> CodeStubAssembler::GetSharedFunctionInfoCode(
// IsFunctionTemplateInfo: API call
BIND(&check_is_function_template_info);
// This is the default branch, so assert that we have the expected data type.
CSA_ASSERT(
this, Word32Equal(data_type, Int32Constant(FUNCTION_TEMPLATE_INFO_TYPE)));
DCHECK(!Builtins::IsLazy(Builtins::kHandleApiCall));
sfi_code = HeapConstant(BUILTIN_CODE(isolate(), HandleApiCall));
Goto(&done);
// IsInterpreterData: Interpret bytecode
BIND(&check_is_interpreter_data);
// This is the default branch, so assert that we have the expected data type.
CSA_ASSERT(this,
Word32Equal(data_type, Int32Constant(INTERPRETER_DATA_TYPE)));
sfi_code = CAST(LoadObjectField(
CAST(sfi_data), InterpreterData::kInterpreterTrampolineOffset));
Goto(&done);
BIND(&done);
return sfi_code.value();
}

View File

@ -749,6 +749,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Load the "prototype" property of a JSFunction.
Node* LoadJSFunctionPrototype(Node* function, Label* if_bailout);
Node* LoadSharedFunctionInfoBytecodeArray(Node* shared);
// Store the floating point value of a HeapNumber.
void StoreHeapNumberValue(SloppyTNode<HeapNumber> object,
SloppyTNode<Float64T> value);

View File

@ -309,9 +309,48 @@ bool UseAsmWasm(FunctionLiteral* literal, bool asm_wasm_broken) {
return literal->scope()->IsAsmModule();
}
void InstallBytecodeArray(Handle<BytecodeArray> bytecode_array,
Handle<SharedFunctionInfo> shared_info,
ParseInfo* parse_info, Isolate* isolate) {
if (!FLAG_interpreted_frames_native_stack) {
shared_info->set_bytecode_array(*bytecode_array);
return;
}
Handle<Code> code;
{
CodeSpaceMemoryModificationScope code_allocation(isolate->heap());
code = isolate->factory()->CopyCode(
BUILTIN_CODE(isolate, InterpreterEntryTrampoline));
}
Handle<InterpreterData> interpreter_data = Handle<InterpreterData>::cast(
isolate->factory()->NewStruct(INTERPRETER_DATA_TYPE, TENURED));
interpreter_data->set_bytecode_array(*bytecode_array);
interpreter_data->set_interpreter_trampoline(*code);
shared_info->set_interpreter_data(*interpreter_data);
Handle<Script> script = parse_info->script();
Handle<AbstractCode> abstract_code = Handle<AbstractCode>::cast(code);
int line_num =
Script::GetLineNumber(script, shared_info->StartPosition()) + 1;
int column_num =
Script::GetColumnNumber(script, shared_info->StartPosition()) + 1;
String* script_name = script->name()->IsString()
? String::cast(script->name())
: isolate->heap()->empty_string();
CodeEventListener::LogEventsAndTags log_tag = Logger::ToNativeByScript(
CodeEventListener::INTERPRETED_FUNCTION_TAG, *script);
PROFILE(isolate, CodeCreateEvent(log_tag, *abstract_code, *shared_info,
script_name, line_num, column_num));
}
void InstallUnoptimizedCode(UnoptimizedCompilationInfo* compilation_info,
Handle<SharedFunctionInfo> shared_info,
Isolate* isolate) {
ParseInfo* parse_info, Isolate* isolate) {
DCHECK_EQ(shared_info->language_mode(),
compilation_info->literal()->language_mode());
@ -327,7 +366,8 @@ void InstallUnoptimizedCode(UnoptimizedCompilationInfo* compilation_info,
Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
isolate, compilation_info->feedback_vector_spec());
shared_info->set_bytecode_array(*compilation_info->bytecode_array());
InstallBytecodeArray(compilation_info->bytecode_array(), shared_info,
parse_info, isolate);
shared_info->set_feedback_metadata(*feedback_metadata);
} else {
DCHECK(compilation_info->has_asm_wasm_data());
@ -382,7 +422,7 @@ CompilationJob::Status FinalizeUnoptimizedCompilationJob(
CompilationJob::Status status = job->FinalizeJob(shared_info, isolate);
if (status == CompilationJob::SUCCEEDED) {
InstallUnoptimizedCode(compilation_info, shared_info, isolate);
InstallUnoptimizedCode(compilation_info, shared_info, parse_info, isolate);
CodeEventListener::LogEventsAndTags log_tag;
if (parse_info->is_toplevel()) {
log_tag = compilation_info->is_eval() ? CodeEventListener::EVAL_TAG

View File

@ -521,7 +521,7 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(
: local_zone_(local_zone),
jsgraph_(jsgraph),
invocation_frequency_(invocation_frequency),
bytecode_array_(handle(shared_info->bytecode_array())),
bytecode_array_(handle(shared_info->GetBytecodeArray())),
feedback_vector_(feedback_vector),
type_hint_lowering_(jsgraph, feedback_vector, flags),
frame_state_function_info_(common()->CreateFrameStateFunctionInfo(

View File

@ -38,6 +38,7 @@ class PromiseFulfillReactionJobTask;
class PromiseReaction;
class PromiseReactionJobTask;
class PromiseRejectReactionJobTask;
class InterpreterData;
class Factory;
class Zone;

View File

@ -495,7 +495,7 @@ Reduction JSCreateLowering::ReduceJSCreateGeneratorObject(Node* node) {
// Allocate a register file.
DCHECK(js_function->shared()->HasBytecodeArray());
int size = js_function->shared()->bytecode_array()->register_count();
int size = js_function->shared()->GetBytecodeArray()->register_count();
AllocationBuilder ab(jsgraph(), effect, control);
ab.AllocateArray(size, factory()->fixed_array_map());
for (int i = 0; i < size; ++i) {

View File

@ -62,7 +62,7 @@ bool CanInlineFunction(Handle<SharedFunctionInfo> shared) {
if (!shared->HasBytecodeArray()) return false;
// Quick check on the size of the bytecode to avoid inlining large functions.
if (shared->bytecode_array()->length() > FLAG_max_inlined_bytecode_size) {
if (shared->GetBytecodeArray()->length() > FLAG_max_inlined_bytecode_size) {
return false;
}
@ -72,7 +72,7 @@ bool CanInlineFunction(Handle<SharedFunctionInfo> shared) {
bool IsSmallInlineFunction(Handle<SharedFunctionInfo> shared) {
// Forcibly inline small functions.
// Don't forcibly inline functions that weren't compiled yet.
if (shared->HasBytecodeArray() && shared->bytecode_array()->length() <=
if (shared->HasBytecodeArray() && shared->GetBytecodeArray()->length() <=
FLAG_max_inlined_bytecode_size_small) {
return true;
}
@ -132,7 +132,7 @@ Reduction JSInliningHeuristic::Reduce(Node* node) {
}
if (candidate.can_inline_function[i]) {
can_inline = true;
candidate.total_size += shared->bytecode_array()->length();
candidate.total_size += shared->GetBytecodeArray()->length();
}
if (!IsSmallInlineFunction(shared)) {
small_inline = false;
@ -610,7 +610,7 @@ Reduction JSInliningHeuristic::InlineCandidate(Candidate const& candidate,
: handle(candidate.functions[0]->shared());
Reduction const reduction = inliner_.ReduceJSCall(node);
if (reduction.Changed()) {
cumulative_count_ += shared->bytecode_array()->length();
cumulative_count_ += shared->GetBytecodeArray()->length();
}
return reduction;
}
@ -679,7 +679,7 @@ Reduction JSInliningHeuristic::InlineCandidate(Candidate const& candidate,
// Killing the call node is not strictly necessary, but it is safer to
// make sure we do not resurrect the node.
node->Kill();
cumulative_count_ += function->shared()->bytecode_array()->length();
cumulative_count_ += function->shared()->GetBytecodeArray()->length();
}
}
}
@ -720,7 +720,7 @@ void JSInliningHeuristic::PrintCandidates() {
candidate.functions[i].is_null()
? candidate.shared_info
: handle(candidate.functions[i]->shared());
PrintF(" - size:%d, name: %s\n", shared->bytecode_array()->length(),
PrintF(" - size:%d, name: %s\n", shared->GetBytecodeArray()->length(),
shared->DebugName()->ToCString().get());
}
}

View File

@ -16,10 +16,10 @@ namespace compiler {
OsrHelper::OsrHelper(OptimizedCompilationInfo* info)
: parameter_count_(
info->shared_info()->bytecode_array()->parameter_count()),
info->shared_info()->GetBytecodeArray()->parameter_count()),
stack_slot_count_(
InterpreterFrameConstants::RegisterStackSlotCount(
info->shared_info()->bytecode_array()->register_count()) +
info->shared_info()->GetBytecodeArray()->register_count()) +
InterpreterFrameConstants::kExtraSlotCount) {}
void OsrHelper::SetupFrame(Frame* frame) {

View File

@ -794,7 +794,7 @@ class PipelineCompilationJob final : public OptimizedCompilationJob {
PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl(
Isolate* isolate) {
if (compilation_info()->shared_info()->bytecode_array()->length() >
if (compilation_info()->shared_info()->GetBytecodeArray()->length() >
kMaxBytecodeSizeForTurbofan) {
return AbortOptimization(BailoutReason::kFunctionTooBig);
}

View File

@ -318,6 +318,7 @@ Type::bitset BitsetType::Lub(i::Map* map) {
case SMALL_ORDERED_HASH_MAP_TYPE:
case SMALL_ORDERED_HASH_SET_TYPE:
case PROTOTYPE_INFO_TYPE:
case INTERPRETER_DATA_TYPE:
case TUPLE2_TYPE:
case TUPLE3_TYPE:
case WASM_COMPILED_MODULE_TYPE:

View File

@ -890,7 +890,7 @@ DebugEvaluate::SideEffectState DebugEvaluate::FunctionGetSideEffectState(
DCHECK(info->is_compiled());
if (info->HasBytecodeArray()) {
// Check bytecodes against whitelist.
Handle<BytecodeArray> bytecode_array(info->bytecode_array());
Handle<BytecodeArray> bytecode_array(info->GetBytecodeArray());
if (FLAG_trace_side_effect_free_debug_evaluate) bytecode_array->Print();
bool requires_runtime_checks = false;
for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done();

View File

@ -1232,7 +1232,7 @@ void Debug::PrepareFunctionForDebugExecution(
Handle<Object> maybe_debug_bytecode_array =
isolate_->factory()->undefined_value();
if (shared->HasBytecodeArray()) {
Handle<BytecodeArray> original(shared->bytecode_array());
Handle<BytecodeArray> original(shared->GetBytecodeArray());
maybe_debug_bytecode_array =
isolate_->factory()->CopyBytecodeArray(original);
}
@ -2418,7 +2418,7 @@ bool Debug::PerformSideEffectCheckAtBytecode(InterpretedFrame* frame) {
DCHECK_EQ(isolate_->debug_execution_mode(), DebugInfo::kSideEffects);
SharedFunctionInfo* shared = frame->function()->shared();
BytecodeArray* bytecode_array = shared->bytecode_array();
BytecodeArray* bytecode_array = shared->GetBytecodeArray();
int offset = frame->GetBytecodeOffset();
interpreter::BytecodeArrayAccessor bytecode_accessor(handle(bytecode_array),
offset);

View File

@ -827,7 +827,11 @@ void LiveEdit::ReplaceFunctionCode(
// Clear old bytecode. This will trigger self-healing if we do not install
// new bytecode.
shared_info->FlushCompiled();
shared_info->set_bytecode_array(new_shared_info->bytecode_array());
if (new_shared_info->HasInterpreterData()) {
shared_info->set_interpreter_data(new_shared_info->interpreter_data());
} else {
shared_info->set_bytecode_array(new_shared_info->GetBytecodeArray());
}
if (shared_info->HasBreakInfo()) {
// Existing break points will be re-applied. Reset the debug info here.
@ -989,7 +993,7 @@ void LiveEdit::PatchFunctionPositions(Handle<JSArray> shared_info_array,
info->set_function_token_position(new_function_token_pos);
if (info->HasBytecodeArray()) {
TranslateSourcePositionTable(handle(info->bytecode_array()),
TranslateSourcePositionTable(handle(info->GetBytecodeArray()),
position_change_array);
}
if (info->HasBreakInfo()) {

View File

@ -548,7 +548,8 @@ int LookupCatchHandler(TranslatedFrame* translated_frame, int* data_out) {
switch (translated_frame->kind()) {
case TranslatedFrame::kInterpretedFunction: {
int bytecode_offset = translated_frame->node_id().ToInt();
HandlerTable table(translated_frame->raw_shared_info()->bytecode_array());
HandlerTable table(
translated_frame->raw_shared_info()->GetBytecodeArray());
return table.LookupRange(bytecode_offset, data_out, nullptr);
}
case TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch: {
@ -891,7 +892,7 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
output_offset -= kPointerSize;
Object* bytecode_array = shared->HasBreakInfo()
? shared->GetDebugInfo()->DebugBytecodeArray()
: shared->bytecode_array();
: shared->GetBytecodeArray();
WriteValueToOutput(bytecode_array, 0, frame_index, output_offset,
"bytecode array ");
@ -2462,7 +2463,7 @@ Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code* code, Address pc) {
int Deoptimizer::ComputeSourcePositionFromBytecodeArray(
SharedFunctionInfo* shared, BailoutId node_id) {
DCHECK(shared->HasBytecodeArray());
return AbstractCode::cast(shared->bytecode_array())
return AbstractCode::cast(shared->GetBytecodeArray())
->SourcePosition(node_id.ToInt());
}

View File

@ -1229,6 +1229,9 @@ DEFINE_BOOL(prof_browser_mode, true,
DEFINE_STRING(logfile, "v8.log", "Specify the name of the log file.")
DEFINE_BOOL(logfile_per_isolate, true, "Separate log files for each isolate.")
DEFINE_BOOL(ll_prof, false, "Enable low-level linux profiler.")
DEFINE_BOOL(interpreted_frames_native_stack, false,
"Show interpreted frames on the native stack (useful for external "
"profilers).")
DEFINE_BOOL(perf_basic_prof, false,
"Enable perf linux profiler (basic support).")
DEFINE_NEG_IMPLICATION(perf_basic_prof, compact_code_space)

View File

@ -169,7 +169,8 @@ bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const {
namespace {
bool IsInterpreterFramePc(Isolate* isolate, Address pc) {
bool IsInterpreterFramePc(Isolate* isolate, Address pc,
StackFrame::State* state) {
Code* interpreter_entry_trampoline =
isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
Code* interpreter_bytecode_advance =
@ -177,12 +178,30 @@ bool IsInterpreterFramePc(Isolate* isolate, Address pc) {
Code* interpreter_bytecode_dispatch =
isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
return (pc >= interpreter_entry_trampoline->InstructionStart() &&
pc < interpreter_entry_trampoline->InstructionEnd()) ||
(pc >= interpreter_bytecode_advance->InstructionStart() &&
pc < interpreter_bytecode_advance->InstructionEnd()) ||
(pc >= interpreter_bytecode_dispatch->InstructionStart() &&
pc < interpreter_bytecode_dispatch->InstructionEnd());
if (interpreter_entry_trampoline->contains(pc) ||
interpreter_bytecode_advance->contains(pc) ||
interpreter_bytecode_dispatch->contains(pc)) {
return true;
} else if (FLAG_interpreted_frames_native_stack) {
intptr_t marker = Memory::intptr_at(
state->fp + CommonFrameConstants::kContextOrFrameTypeOffset);
MSAN_MEMORY_IS_INITIALIZED(
state->fp + StandardFrameConstants::kFunctionOffset, kPointerSize);
Object* maybe_function =
Memory::Object_at(state->fp + StandardFrameConstants::kFunctionOffset);
// There's no need to run a full ContainsSlow if we know the frame can't be
// an InterpretedFrame, so we do these fast checks first
if (StackFrame::IsTypeMarker(marker) || maybe_function->IsSmi()) {
return false;
} else if (!isolate->heap()->code_space()->ContainsSlow(pc)) {
return false;
}
interpreter_entry_trampoline =
isolate->heap()->GcSafeFindCodeForInnerPointer(pc);
return interpreter_entry_trampoline->is_interpreter_trampoline_builtin();
} else {
return false;
}
}
DISABLE_ASAN Address ReadMemoryAt(Address address) {
@ -229,7 +248,7 @@ SafeStackFrameIterator::SafeStackFrameIterator(
if (IsValidStackAddress(sp)) {
MSAN_MEMORY_IS_INITIALIZED(sp, kPointerSize);
Address tos = ReadMemoryAt(reinterpret_cast<Address>(sp));
if (IsInterpreterFramePc(isolate, tos)) {
if (IsInterpreterFramePc(isolate, tos, &state)) {
state.pc_address = reinterpret_cast<Address*>(sp);
advance_frame = false;
}
@ -436,8 +455,8 @@ StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
if (!StackFrame::IsTypeMarker(marker)) {
if (maybe_function->IsSmi()) {
return NATIVE;
} else if (IsInterpreterFramePc(iterator->isolate(),
*(state->pc_address))) {
} else if (IsInterpreterFramePc(iterator->isolate(), *(state->pc_address),
state)) {
return INTERPRETED;
} else {
return OPTIMIZED;
@ -1641,7 +1660,7 @@ int InterpretedFrame::position() const {
int InterpretedFrame::LookupExceptionHandlerInTable(
int* context_register, HandlerTable::CatchPrediction* prediction) {
HandlerTable table(function()->shared()->bytecode_array());
HandlerTable table(function()->shared()->GetBytecodeArray());
return table.LookupRange(GetBytecodeOffset(), context_register, prediction);
}
@ -1710,7 +1729,7 @@ void InterpretedFrame::WriteInterpreterRegister(int register_index,
void InterpretedFrame::Summarize(std::vector<FrameSummary>* functions) const {
DCHECK(functions->empty());
AbstractCode* abstract_code =
AbstractCode::cast(function()->shared()->bytecode_array());
AbstractCode::cast(function()->shared()->GetBytecodeArray());
FrameSummary::JavaScriptFrameSummary summary(
isolate(), receiver(), function(), abstract_code, GetBytecodeOffset(),
IsConstructor());

View File

@ -243,6 +243,7 @@
V(intl_initialized_marker_symbol) \
V(intl_pattern_symbol) \
V(intl_resolved_symbol) \
V(interpreter_trampoline_symbol) \
V(megamorphic_symbol) \
V(native_context_index_symbol) \
V(nonextensible_symbol) \

View File

@ -28,6 +28,7 @@ namespace interpreter {
V(EmptyFixedArray, empty_fixed_array) \
V(HomeObjectSymbol, home_object_symbol) \
V(IteratorSymbol, iterator_symbol) \
V(InterpreterTrampolineSymbol, interpreter_trampoline_symbol) \
V(NaN, nan_value)
// A helper class for constructing constant arrays for the

View File

@ -1715,6 +1715,12 @@ void PreParsedScopeData::PreParsedScopeDataVerify() {
CHECK(child_data()->IsFixedArray());
}
void InterpreterData::InterpreterDataVerify() {
CHECK(IsInterpreterData());
CHECK(bytecode_array()->IsBytecodeArray());
CHECK(interpreter_trampoline()->IsCode());
}
#endif // VERIFY_HEAP
#ifdef DEBUG

View File

@ -2609,7 +2609,7 @@ void JSFunction::CompleteInobjectSlackTrackingIfActive() {
AbstractCode* JSFunction::abstract_code() {
if (IsInterpreted()) {
return AbstractCode::cast(shared()->bytecode_array());
return AbstractCode::cast(shared()->GetBytecodeArray());
} else {
return AbstractCode::cast(code());
}

View File

@ -1214,7 +1214,7 @@ void JSFunction::JSFunctionPrint(std::ostream& os) { // NOLINT
if (IsInterpreted()) {
os << "\n - interpreted";
if (shared()->HasBytecodeArray()) {
os << "\n - bytecode: " << shared()->bytecode_array();
os << "\n - bytecode: " << shared()->GetBytecodeArray();
}
}
if (WasmExportedFunction::IsWasmExportedFunction(this)) {
@ -1893,6 +1893,13 @@ void PreParsedScopeData::PreParsedScopeDataPrint(std::ostream& os) { // NOLINT
os << "\n";
}
void InterpreterData::InterpreterDataPrint(std::ostream& os) { // NOLINT
HeapObject::PrintHeader(os, "InterpreterData");
os << "\n - bytecode_array: " << Brief(bytecode_array());
os << "\n - interpreter_trampoline: " << Brief(interpreter_trampoline());
os << "\n";
}
#endif // OBJECT_PRINT
// TODO(cbruni): remove once the new maptracer is in place.

View File

@ -17646,7 +17646,7 @@ void CompilationCacheTable::Age() {
}
} else if (get(entry_index)->IsFixedArray()) {
SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index));
if (info->IsInterpreted() && info->bytecode_array()->IsOld()) {
if (info->IsInterpreted() && info->GetBytecodeArray()->IsOld()) {
for (int i = 0; i < kEntrySize; i++) {
NoWriteBarrierSet(this, entry_index + i, the_hole_value);
}
@ -19436,7 +19436,7 @@ int JSGeneratorObject::source_position() const {
// is used in the source position table, hence the subtraction.
code_offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
AbstractCode* code =
AbstractCode::cast(function()->shared()->bytecode_array());
AbstractCode::cast(function()->shared()->GetBytecodeArray());
return code->SourcePosition(code_offset);
}

View File

@ -386,6 +386,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(DEBUG_INFO_TYPE) \
V(FUNCTION_TEMPLATE_INFO_TYPE) \
V(INTERCEPTOR_INFO_TYPE) \
V(INTERPRETER_DATA_TYPE) \
V(MODULE_INFO_ENTRY_TYPE) \
V(MODULE_TYPE) \
V(OBJECT_TEMPLATE_INFO_TYPE) \
@ -558,6 +559,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(DEBUG_INFO, DebugInfo, debug_info) \
V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \
V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \
V(INTERPRETER_DATA, InterpreterData, interpreter_data) \
V(MODULE_INFO_ENTRY, ModuleInfoEntry, module_info_entry) \
V(MODULE, Module, module) \
V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \
@ -752,6 +754,7 @@ enum InstanceType : uint16_t {
DEBUG_INFO_TYPE,
FUNCTION_TEMPLATE_INFO_TYPE,
INTERCEPTOR_INFO_TYPE,
INTERPRETER_DATA_TYPE,
MODULE_INFO_ENTRY_TYPE,
MODULE_TYPE,
OBJECT_TEMPLATE_INFO_TYPE,

View File

@ -341,8 +341,10 @@ void Code::initialize_flags(Kind kind, bool has_unwinding_info,
inline bool Code::is_interpreter_trampoline_builtin() const {
Builtins* builtins = GetIsolate()->builtins();
Code* interpreter_entry_trampoline =
builtins->builtin(Builtins::kInterpreterEntryTrampoline);
bool is_interpreter_trampoline =
(this == builtins->builtin(Builtins::kInterpreterEntryTrampoline) ||
(builtin_index() == interpreter_entry_trampoline->builtin_index() ||
this == builtins->builtin(Builtins::kInterpreterEnterBytecodeAdvance) ||
this == builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch));
DCHECK_IMPLIES(is_interpreter_trampoline, !Builtins::IsLazy(builtin_index()));
@ -351,9 +353,11 @@ inline bool Code::is_interpreter_trampoline_builtin() const {
inline bool Code::checks_optimization_marker() const {
Builtins* builtins = GetIsolate()->builtins();
Code* interpreter_entry_trampoline =
builtins->builtin(Builtins::kInterpreterEntryTrampoline);
bool checks_marker =
(this == builtins->builtin(Builtins::kCompileLazy) ||
this == builtins->builtin(Builtins::kInterpreterEntryTrampoline));
builtin_index() == interpreter_entry_trampoline->builtin_index());
DCHECK_IMPLIES(checks_marker, !Builtins::IsLazy(builtin_index()));
return checks_marker ||
(kind() == OPTIMIZED_FUNCTION && marked_for_deoptimization());

View File

@ -39,7 +39,7 @@ bool DebugInfo::HasDebugBytecodeArray() {
BytecodeArray* DebugInfo::OriginalBytecodeArray() {
DCHECK(HasDebugBytecodeArray());
return shared()->bytecode_array();
return shared()->GetBytecodeArray();
}
BytecodeArray* DebugInfo::DebugBytecodeArray() {

View File

@ -19,6 +19,11 @@ CAST_ACCESSOR(PreParsedScopeData)
ACCESSORS(PreParsedScopeData, scope_data, PodArray<uint8_t>, kScopeDataOffset)
ACCESSORS(PreParsedScopeData, child_data, FixedArray, kChildDataOffset)
CAST_ACCESSOR(InterpreterData)
ACCESSORS(InterpreterData, bytecode_array, BytecodeArray, kBytecodeArrayOffset)
ACCESSORS(InterpreterData, interpreter_trampoline, Code,
kInterpreterTrampolineOffset)
TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
CAST_ACCESSOR(SharedFunctionInfo)
DEFINE_DEOPT_ELEMENT_ACCESSORS(SharedFunctionInfo, Object)
@ -87,7 +92,7 @@ void SharedFunctionInfo::SetName(String* name) {
AbstractCode* SharedFunctionInfo::abstract_code() {
if (HasBytecodeArray()) {
return AbstractCode::cast(bytecode_array());
return AbstractCode::cast(GetBytecodeArray());
} else {
return AbstractCode::cast(GetCode());
}
@ -291,6 +296,11 @@ Code* SharedFunctionInfo::GetCode() const {
// Having a code object means we should run it.
DCHECK(HasCodeObject());
return Code::cast(data);
} else if (data->IsInterpreterData()) {
Code* code = InterpreterTrampoline();
DCHECK(code->IsCode());
DCHECK(code->is_interpreter_trampoline_builtin());
return code;
}
UNREACHABLE();
}
@ -417,19 +427,45 @@ FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
}
bool SharedFunctionInfo::HasBytecodeArray() const {
return function_data()->IsBytecodeArray();
return function_data()->IsBytecodeArray() ||
function_data()->IsInterpreterData();
}
BytecodeArray* SharedFunctionInfo::bytecode_array() const {
BytecodeArray* SharedFunctionInfo::GetBytecodeArray() const {
DCHECK(HasBytecodeArray());
return BytecodeArray::cast(function_data());
if (function_data()->IsBytecodeArray()) {
return BytecodeArray::cast(function_data());
} else {
DCHECK(function_data()->IsInterpreterData());
return InterpreterData::cast(function_data())->bytecode_array();
}
}
void SharedFunctionInfo::set_bytecode_array(BytecodeArray* bytecode) {
void SharedFunctionInfo::set_bytecode_array(class BytecodeArray* bytecode) {
DCHECK(function_data() == Smi::FromEnum(Builtins::kCompileLazy));
set_function_data(bytecode);
}
Code* SharedFunctionInfo::InterpreterTrampoline() const {
DCHECK(HasInterpreterData());
return interpreter_data()->interpreter_trampoline();
}
bool SharedFunctionInfo::HasInterpreterData() const {
return function_data()->IsInterpreterData();
}
InterpreterData* SharedFunctionInfo::interpreter_data() const {
DCHECK(HasInterpreterData());
return InterpreterData::cast(function_data());
}
void SharedFunctionInfo::set_interpreter_data(
InterpreterData* interpreter_data) {
DCHECK(FLAG_interpreted_frames_native_stack);
set_function_data(interpreter_data);
}
bool SharedFunctionInfo::HasAsmWasmData() const {
return function_data()->IsFixedArray();
}

View File

@ -35,6 +35,24 @@ class PreParsedScopeData : public Struct {
DISALLOW_IMPLICIT_CONSTRUCTORS(PreParsedScopeData);
};
class InterpreterData : public Struct {
public:
DECL_ACCESSORS(bytecode_array, BytecodeArray)
DECL_ACCESSORS(interpreter_trampoline, Code)
static const int kBytecodeArrayOffset = Struct::kHeaderSize;
static const int kInterpreterTrampolineOffset =
kBytecodeArrayOffset + kPointerSize;
static const int kSize = kInterpreterTrampolineOffset + kPointerSize;
DECL_CAST(InterpreterData)
DECL_PRINTER(InterpreterData)
DECL_VERIFIER(InterpreterData)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(InterpreterData);
};
// SharedFunctionInfo describes the JSFunction information that can be
// shared by multiple instances of the function.
class SharedFunctionInfo : public HeapObject {
@ -143,6 +161,8 @@ class SharedFunctionInfo : public HeapObject {
// Currently it has one of:
// - a FunctionTemplateInfo to make benefit the API [IsApiFunction()].
// - a BytecodeArray for the interpreter [HasBytecodeArray()].
// - a InterpreterData with the BytecodeArray and a copy of the
// interpreter trampoline [HasInterpreterData()]
// - a FixedArray with Asm->Wasm conversion [HasAsmWasmData()].
// - a Smi containing the builtin id [HasBuiltinId()]
// - a PreParsedScopeData for the parser [HasPreParsedScopeData()]
@ -153,8 +173,12 @@ class SharedFunctionInfo : public HeapObject {
inline FunctionTemplateInfo* get_api_func_data();
inline void set_api_func_data(FunctionTemplateInfo* data);
inline bool HasBytecodeArray() const;
inline BytecodeArray* bytecode_array() const;
inline void set_bytecode_array(BytecodeArray* bytecode);
inline BytecodeArray* GetBytecodeArray() const;
inline void set_bytecode_array(class BytecodeArray* bytecode);
inline Code* InterpreterTrampoline() const;
inline bool HasInterpreterData() const;
inline InterpreterData* interpreter_data() const;
inline void set_interpreter_data(InterpreterData* interpreter_data);
inline bool HasAsmWasmData() const;
inline FixedArray* asm_wasm_data() const;
inline void set_asm_wasm_data(FixedArray* data);

View File

@ -134,8 +134,8 @@ void RuntimeProfiler::AttemptOnStackReplacement(JavaScriptFrame* frame,
DCHECK_EQ(StackFrame::INTERPRETED, frame->type());
DCHECK(shared->HasBytecodeArray());
int level = shared->bytecode_array()->osr_loop_nesting_level();
shared->bytecode_array()->set_osr_loop_nesting_level(
int level = shared->GetBytecodeArray()->osr_loop_nesting_level();
shared->GetBytecodeArray()->set_osr_loop_nesting_level(
Min(level + loop_nesting_levels, AbstractCode::kMaxLoopNestingMarker));
}
@ -184,7 +184,7 @@ bool RuntimeProfiler::MaybeOSR(JSFunction* function, JavaScriptFrame* frame) {
int64_t allowance =
kOSRBytecodeSizeAllowanceBase +
static_cast<int64_t>(ticks) * kOSRBytecodeSizeAllowancePerTick;
if (shared->bytecode_array()->length() <= allowance) {
if (shared->GetBytecodeArray()->length() <= allowance) {
AttemptOnStackReplacement(frame);
}
return true;
@ -197,17 +197,17 @@ OptimizationReason RuntimeProfiler::ShouldOptimize(JSFunction* function,
SharedFunctionInfo* shared = function->shared();
int ticks = function->feedback_vector()->profiler_ticks();
if (shared->bytecode_array()->length() > kMaxBytecodeSizeForOpt) {
if (shared->GetBytecodeArray()->length() > kMaxBytecodeSizeForOpt) {
return OptimizationReason::kDoNotOptimize;
}
int ticks_for_optimization =
kProfilerTicksBeforeOptimization +
(shared->bytecode_array()->length() / kBytecodeSizeAllowancePerTick);
(shared->GetBytecodeArray()->length() / kBytecodeSizeAllowancePerTick);
if (ticks >= ticks_for_optimization) {
return OptimizationReason::kHotAndStable;
} else if (!any_ic_changed_ &&
shared->bytecode_array()->length() < kMaxBytecodeSizeForEarlyOpt) {
} else if (!any_ic_changed_ && shared->GetBytecodeArray()->length() <
kMaxBytecodeSizeForEarlyOpt) {
// If no IC was patched since the last tick and this function is very
// small, optimistically optimize it now.
return OptimizationReason::kSmallFunction;
@ -220,7 +220,7 @@ OptimizationReason RuntimeProfiler::ShouldOptimize(JSFunction* function,
PrintF("ICs changed]\n");
} else {
PrintF(" too large for small function optimization: %d/%d]\n",
shared->bytecode_array()->length(), kMaxBytecodeSizeForEarlyOpt);
shared->GetBytecodeArray()->length(), kMaxBytecodeSizeForEarlyOpt);
}
}
return OptimizationReason::kDoNotOptimize;

View File

@ -53,7 +53,7 @@ RUNTIME_FUNCTION_RETURN_PAIR(Runtime_DebugBreakOnBytecode) {
InterpretedFrame* interpreted_frame =
reinterpret_cast<InterpretedFrame*>(it.frame());
SharedFunctionInfo* shared = interpreted_frame->function()->shared();
BytecodeArray* bytecode_array = shared->bytecode_array();
BytecodeArray* bytecode_array = shared->GetBytecodeArray();
int bytecode_offset = interpreted_frame->GetBytecodeOffset();
Bytecode bytecode = Bytecodes::FromByte(bytecode_array->get(bytecode_offset));

View File

@ -26,7 +26,7 @@ RUNTIME_FUNCTION(Runtime_CreateJSGeneratorObject) {
// Underlying function needs to have bytecode available.
DCHECK(function->shared()->HasBytecodeArray());
int size = function->shared()->bytecode_array()->register_count();
int size = function->shared()->GetBytecodeArray()->register_count();
Handle<FixedArray> register_file = isolate->factory()->NewFixedArray(size);
Handle<JSGeneratorObject> generator =
@ -153,7 +153,7 @@ RUNTIME_FUNCTION(Runtime_AsyncGeneratorHasCatchHandlerForPC) {
SharedFunctionInfo* shared = generator->function()->shared();
DCHECK(shared->HasBytecodeArray());
HandlerTable handler_table(shared->bytecode_array());
HandlerTable handler_table(shared->GetBytecodeArray());
int pc = Smi::cast(generator->input_or_debug_pos())->value();
HandlerTable::CatchPrediction catch_prediction = HandlerTable::ASYNC_AWAIT;

View File

@ -1352,7 +1352,7 @@ TEST(CompilationCacheCachingBehavior) {
CHECK(shared->HasBytecodeArray());
const int kAgingThreshold = 6;
for (int i = 0; i < kAgingThreshold; i++) {
shared->bytecode_array()->MakeOlder();
shared->GetBytecodeArray()->MakeOlder();
}
}

View File

@ -95,7 +95,7 @@ BytecodeExpectationsPrinter::GetBytecodeArrayForGlobal(
i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*function));
i::Handle<i::BytecodeArray> bytecodes =
i::handle(js_function->shared()->bytecode_array(), i_isolate());
i::handle(js_function->shared()->GetBytecodeArray(), i_isolate());
return bytecodes;
}
@ -104,15 +104,16 @@ i::Handle<i::BytecodeArray>
BytecodeExpectationsPrinter::GetBytecodeArrayForModule(
v8::Local<v8::Module> module) const {
i::Handle<i::Module> i_module = v8::Utils::OpenHandle(*module);
return i::handle(SharedFunctionInfo::cast(i_module->code())->bytecode_array(),
i_isolate());
return i::handle(
SharedFunctionInfo::cast(i_module->code())->GetBytecodeArray(),
i_isolate());
}
i::Handle<i::BytecodeArray>
BytecodeExpectationsPrinter::GetBytecodeArrayForScript(
v8::Local<v8::Script> script) const {
i::Handle<i::JSFunction> js_function = v8::Utils::OpenHandle(*script);
return i::handle(js_function->shared()->bytecode_array(), i_isolate());
return i::handle(js_function->shared()->GetBytecodeArray(), i_isolate());
}
void BytecodeExpectationsPrinter::PrintEscapedString(

View File

@ -5029,6 +5029,29 @@ TEST(InterpreterGenerators) {
}
}
TEST(InterpreterWithNativeStack) {
i::FLAG_interpreted_frames_native_stack = true;
HandleAndZoneScope handles;
i::Isolate* isolate = handles.main_isolate();
const char* source_text =
"function testInterpreterWithNativeStack(a,b) { return a + b };";
i::Handle<i::Object> o = v8::Utils::OpenHandle(*v8_compile(source_text));
i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
CHECK(f->shared()->HasBytecodeArray());
i::Code* code = f->shared()->GetCode();
i::Handle<i::Code> interpreter_entry_trampoline =
BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
CHECK(code->IsCode());
CHECK(code->is_interpreter_trampoline_builtin());
CHECK_NE(code->InstructionStart(),
interpreter_entry_trampoline->InstructionStart());
}
} // namespace interpreter
} // namespace internal
} // namespace v8

View File

@ -171,7 +171,7 @@ Handle<BytecodeArray> OptimizedBytecodeSourcePositionTester::MakeBytecode(
.ToLocalChecked());
Handle<JSFunction> function =
Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function));
return handle(function->shared()->bytecode_array());
return handle(function->shared()->GetBytecodeArray());
}
void OptimizedBytecodeSourcePositionTester::SetOptimizationFlags(

View File

@ -778,6 +778,29 @@ TEST(LogAll) {
isolate->Dispose();
}
TEST(LogInterpretedFramesNativeStack) {
SETUP_FLAGS();
i::FLAG_interpreted_frames_native_stack = true;
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
v8::Isolate* isolate = v8::Isolate::New(create_params);
{
ScopedLoggerInitializer logger(saved_log, saved_prof, isolate);
const char* source_text =
"function testLogInterpretedFramesNativeStack(a,b) { return a + b };"
"testLogInterpretedFramesNativeStack('1', 1);";
CompileRun(source_text);
logger.StopLogging();
CHECK(logger.FindLine("InterpretedFunction",
"testLogInterpretedFramesNativeStack"));
}
isolate->Dispose();
}
TEST(TraceMaps) {
SETUP_FLAGS();
i::FLAG_trace_maps = true;

View File

@ -2048,7 +2048,7 @@ TEST(CodeSerializerAfterExecute) {
Handle<SharedFunctionInfo> sfi = v8::Utils::OpenHandle(*script);
CHECK(sfi->HasBytecodeArray());
BytecodeArray* bytecode = sfi->bytecode_array();
BytecodeArray* bytecode = sfi->GetBytecodeArray();
CHECK_EQ(bytecode->interrupt_budget(),
interpreter::Interpreter::InterruptBudget());
CHECK_EQ(bytecode->osr_loop_nesting_level(), 0);

View File

@ -65,53 +65,54 @@ INSTANCE_TYPES = {
161: "DEBUG_INFO_TYPE",
162: "FUNCTION_TEMPLATE_INFO_TYPE",
163: "INTERCEPTOR_INFO_TYPE",
164: "MODULE_INFO_ENTRY_TYPE",
165: "MODULE_TYPE",
166: "OBJECT_TEMPLATE_INFO_TYPE",
167: "PROMISE_CAPABILITY_TYPE",
168: "PROMISE_REACTION_TYPE",
169: "PROTOTYPE_INFO_TYPE",
170: "SCRIPT_TYPE",
171: "STACK_FRAME_INFO_TYPE",
172: "TUPLE2_TYPE",
173: "TUPLE3_TYPE",
174: "WASM_COMPILED_MODULE_TYPE",
175: "WASM_DEBUG_INFO_TYPE",
176: "WASM_SHARED_MODULE_DATA_TYPE",
177: "CALLABLE_TASK_TYPE",
178: "CALLBACK_TASK_TYPE",
179: "PROMISE_FULFILL_REACTION_JOB_TASK_TYPE",
180: "PROMISE_REJECT_REACTION_JOB_TASK_TYPE",
181: "PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE",
182: "FIXED_ARRAY_TYPE",
183: "BOILERPLATE_DESCRIPTION_TYPE",
184: "DESCRIPTOR_ARRAY_TYPE",
185: "HASH_TABLE_TYPE",
186: "SCOPE_INFO_TYPE",
187: "TRANSITION_ARRAY_TYPE",
188: "BLOCK_CONTEXT_TYPE",
189: "CATCH_CONTEXT_TYPE",
190: "DEBUG_EVALUATE_CONTEXT_TYPE",
191: "EVAL_CONTEXT_TYPE",
192: "FUNCTION_CONTEXT_TYPE",
193: "MODULE_CONTEXT_TYPE",
194: "NATIVE_CONTEXT_TYPE",
195: "SCRIPT_CONTEXT_TYPE",
196: "WITH_CONTEXT_TYPE",
197: "CALL_HANDLER_INFO_TYPE",
198: "CELL_TYPE",
199: "CODE_DATA_CONTAINER_TYPE",
200: "FEEDBACK_CELL_TYPE",
201: "FEEDBACK_VECTOR_TYPE",
202: "LOAD_HANDLER_TYPE",
203: "PROPERTY_ARRAY_TYPE",
204: "PROPERTY_CELL_TYPE",
205: "SHARED_FUNCTION_INFO_TYPE",
206: "SMALL_ORDERED_HASH_MAP_TYPE",
207: "SMALL_ORDERED_HASH_SET_TYPE",
208: "STORE_HANDLER_TYPE",
209: "WEAK_CELL_TYPE",
210: "WEAK_FIXED_ARRAY_TYPE",
164: "INTERPRETER_DATA_TYPE",
165: "MODULE_INFO_ENTRY_TYPE",
166: "MODULE_TYPE",
167: "OBJECT_TEMPLATE_INFO_TYPE",
168: "PROMISE_CAPABILITY_TYPE",
169: "PROMISE_REACTION_TYPE",
170: "PROTOTYPE_INFO_TYPE",
171: "SCRIPT_TYPE",
172: "STACK_FRAME_INFO_TYPE",
173: "TUPLE2_TYPE",
174: "TUPLE3_TYPE",
175: "WASM_COMPILED_MODULE_TYPE",
176: "WASM_DEBUG_INFO_TYPE",
177: "WASM_SHARED_MODULE_DATA_TYPE",
178: "CALLABLE_TASK_TYPE",
179: "CALLBACK_TASK_TYPE",
180: "PROMISE_FULFILL_REACTION_JOB_TASK_TYPE",
181: "PROMISE_REJECT_REACTION_JOB_TASK_TYPE",
182: "PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE",
183: "FIXED_ARRAY_TYPE",
184: "BOILERPLATE_DESCRIPTION_TYPE",
185: "DESCRIPTOR_ARRAY_TYPE",
186: "HASH_TABLE_TYPE",
187: "SCOPE_INFO_TYPE",
188: "TRANSITION_ARRAY_TYPE",
189: "BLOCK_CONTEXT_TYPE",
190: "CATCH_CONTEXT_TYPE",
191: "DEBUG_EVALUATE_CONTEXT_TYPE",
192: "EVAL_CONTEXT_TYPE",
193: "FUNCTION_CONTEXT_TYPE",
194: "MODULE_CONTEXT_TYPE",
195: "NATIVE_CONTEXT_TYPE",
196: "SCRIPT_CONTEXT_TYPE",
197: "WITH_CONTEXT_TYPE",
198: "CALL_HANDLER_INFO_TYPE",
199: "CELL_TYPE",
200: "CODE_DATA_CONTAINER_TYPE",
201: "FEEDBACK_CELL_TYPE",
202: "FEEDBACK_VECTOR_TYPE",
203: "LOAD_HANDLER_TYPE",
204: "PROPERTY_ARRAY_TYPE",
205: "PROPERTY_CELL_TYPE",
206: "SHARED_FUNCTION_INFO_TYPE",
207: "SMALL_ORDERED_HASH_MAP_TYPE",
208: "SMALL_ORDERED_HASH_SET_TYPE",
209: "STORE_HANDLER_TYPE",
210: "WEAK_CELL_TYPE",
211: "WEAK_FIXED_ARRAY_TYPE",
1024: "JS_PROXY_TYPE",
1025: "JS_GLOBAL_OBJECT_TYPE",
1026: "JS_GLOBAL_PROXY_TYPE",
@ -160,8 +161,8 @@ KNOWN_MAPS = {
("MAP_SPACE", 0x02201): (138, "FreeSpaceMap"),
("MAP_SPACE", 0x02251): (132, "MetaMap"),
("MAP_SPACE", 0x022a1): (131, "NullMap"),
("MAP_SPACE", 0x022f1): (184, "DescriptorArrayMap"),
("MAP_SPACE", 0x02341): (182, "FixedArrayMap"),
("MAP_SPACE", 0x022f1): (185, "DescriptorArrayMap"),
("MAP_SPACE", 0x02341): (183, "FixedArrayMap"),
("MAP_SPACE", 0x02391): (152, "OnePointerFillerMap"),
("MAP_SPACE", 0x023e1): (152, "TwoPointerFillerMap"),
("MAP_SPACE", 0x02431): (131, "UninitializedMap"),
@ -171,62 +172,62 @@ KNOWN_MAPS = {
("MAP_SPACE", 0x02571): (131, "TheHoleMap"),
("MAP_SPACE", 0x025c1): (131, "BooleanMap"),
("MAP_SPACE", 0x02611): (136, "ByteArrayMap"),
("MAP_SPACE", 0x02661): (182, "FixedCOWArrayMap"),
("MAP_SPACE", 0x026b1): (185, "HashTableMap"),
("MAP_SPACE", 0x02661): (183, "FixedCOWArrayMap"),
("MAP_SPACE", 0x026b1): (186, "HashTableMap"),
("MAP_SPACE", 0x02701): (128, "SymbolMap"),
("MAP_SPACE", 0x02751): (72, "OneByteStringMap"),
("MAP_SPACE", 0x027a1): (186, "ScopeInfoMap"),
("MAP_SPACE", 0x027f1): (205, "SharedFunctionInfoMap"),
("MAP_SPACE", 0x027a1): (187, "ScopeInfoMap"),
("MAP_SPACE", 0x027f1): (206, "SharedFunctionInfoMap"),
("MAP_SPACE", 0x02841): (133, "CodeMap"),
("MAP_SPACE", 0x02891): (192, "FunctionContextMap"),
("MAP_SPACE", 0x028e1): (198, "CellMap"),
("MAP_SPACE", 0x02931): (209, "WeakCellMap"),
("MAP_SPACE", 0x02981): (204, "GlobalPropertyCellMap"),
("MAP_SPACE", 0x02891): (193, "FunctionContextMap"),
("MAP_SPACE", 0x028e1): (199, "CellMap"),
("MAP_SPACE", 0x02931): (210, "WeakCellMap"),
("MAP_SPACE", 0x02981): (205, "GlobalPropertyCellMap"),
("MAP_SPACE", 0x029d1): (135, "ForeignMap"),
("MAP_SPACE", 0x02a21): (187, "TransitionArrayMap"),
("MAP_SPACE", 0x02a71): (201, "FeedbackVectorMap"),
("MAP_SPACE", 0x02a21): (188, "TransitionArrayMap"),
("MAP_SPACE", 0x02a71): (202, "FeedbackVectorMap"),
("MAP_SPACE", 0x02ac1): (131, "ArgumentsMarkerMap"),
("MAP_SPACE", 0x02b11): (131, "ExceptionMap"),
("MAP_SPACE", 0x02b61): (131, "TerminationExceptionMap"),
("MAP_SPACE", 0x02bb1): (131, "OptimizedOutMap"),
("MAP_SPACE", 0x02c01): (131, "StaleRegisterMap"),
("MAP_SPACE", 0x02c51): (194, "NativeContextMap"),
("MAP_SPACE", 0x02ca1): (193, "ModuleContextMap"),
("MAP_SPACE", 0x02cf1): (191, "EvalContextMap"),
("MAP_SPACE", 0x02d41): (195, "ScriptContextMap"),
("MAP_SPACE", 0x02d91): (188, "BlockContextMap"),
("MAP_SPACE", 0x02de1): (189, "CatchContextMap"),
("MAP_SPACE", 0x02e31): (196, "WithContextMap"),
("MAP_SPACE", 0x02e81): (190, "DebugEvaluateContextMap"),
("MAP_SPACE", 0x02ed1): (182, "ScriptContextTableMap"),
("MAP_SPACE", 0x02c51): (195, "NativeContextMap"),
("MAP_SPACE", 0x02ca1): (194, "ModuleContextMap"),
("MAP_SPACE", 0x02cf1): (192, "EvalContextMap"),
("MAP_SPACE", 0x02d41): (196, "ScriptContextMap"),
("MAP_SPACE", 0x02d91): (189, "BlockContextMap"),
("MAP_SPACE", 0x02de1): (190, "CatchContextMap"),
("MAP_SPACE", 0x02e31): (197, "WithContextMap"),
("MAP_SPACE", 0x02e81): (191, "DebugEvaluateContextMap"),
("MAP_SPACE", 0x02ed1): (183, "ScriptContextTableMap"),
("MAP_SPACE", 0x02f21): (151, "FeedbackMetadataArrayMap"),
("MAP_SPACE", 0x02f71): (182, "ArrayListMap"),
("MAP_SPACE", 0x02f71): (183, "ArrayListMap"),
("MAP_SPACE", 0x02fc1): (130, "BigIntMap"),
("MAP_SPACE", 0x03011): (183, "BoilerplateDescriptionMap"),
("MAP_SPACE", 0x03011): (184, "BoilerplateDescriptionMap"),
("MAP_SPACE", 0x03061): (137, "BytecodeArrayMap"),
("MAP_SPACE", 0x030b1): (199, "CodeDataContainerMap"),
("MAP_SPACE", 0x030b1): (200, "CodeDataContainerMap"),
("MAP_SPACE", 0x03101): (1057, "ExternalMap"),
("MAP_SPACE", 0x03151): (150, "FixedDoubleArrayMap"),
("MAP_SPACE", 0x031a1): (185, "GlobalDictionaryMap"),
("MAP_SPACE", 0x031f1): (200, "ManyClosuresCellMap"),
("MAP_SPACE", 0x031a1): (186, "GlobalDictionaryMap"),
("MAP_SPACE", 0x031f1): (201, "ManyClosuresCellMap"),
("MAP_SPACE", 0x03241): (1072, "JSMessageObjectMap"),
("MAP_SPACE", 0x03291): (182, "ModuleInfoMap"),
("MAP_SPACE", 0x03291): (183, "ModuleInfoMap"),
("MAP_SPACE", 0x032e1): (134, "MutableHeapNumberMap"),
("MAP_SPACE", 0x03331): (185, "NameDictionaryMap"),
("MAP_SPACE", 0x03381): (200, "NoClosuresCellMap"),
("MAP_SPACE", 0x033d1): (185, "NumberDictionaryMap"),
("MAP_SPACE", 0x03421): (200, "OneClosureCellMap"),
("MAP_SPACE", 0x03471): (185, "OrderedHashMapMap"),
("MAP_SPACE", 0x034c1): (185, "OrderedHashSetMap"),
("MAP_SPACE", 0x03511): (203, "PropertyArrayMap"),
("MAP_SPACE", 0x03561): (197, "SideEffectCallHandlerInfoMap"),
("MAP_SPACE", 0x035b1): (197, "SideEffectFreeCallHandlerInfoMap"),
("MAP_SPACE", 0x03601): (185, "SimpleNumberDictionaryMap"),
("MAP_SPACE", 0x03651): (182, "SloppyArgumentsElementsMap"),
("MAP_SPACE", 0x036a1): (206, "SmallOrderedHashMapMap"),
("MAP_SPACE", 0x036f1): (207, "SmallOrderedHashSetMap"),
("MAP_SPACE", 0x03741): (185, "StringTableMap"),
("MAP_SPACE", 0x03791): (210, "WeakFixedArrayMap"),
("MAP_SPACE", 0x03331): (186, "NameDictionaryMap"),
("MAP_SPACE", 0x03381): (201, "NoClosuresCellMap"),
("MAP_SPACE", 0x033d1): (186, "NumberDictionaryMap"),
("MAP_SPACE", 0x03421): (201, "OneClosureCellMap"),
("MAP_SPACE", 0x03471): (186, "OrderedHashMapMap"),
("MAP_SPACE", 0x034c1): (186, "OrderedHashSetMap"),
("MAP_SPACE", 0x03511): (204, "PropertyArrayMap"),
("MAP_SPACE", 0x03561): (198, "SideEffectCallHandlerInfoMap"),
("MAP_SPACE", 0x035b1): (198, "SideEffectFreeCallHandlerInfoMap"),
("MAP_SPACE", 0x03601): (186, "SimpleNumberDictionaryMap"),
("MAP_SPACE", 0x03651): (183, "SloppyArgumentsElementsMap"),
("MAP_SPACE", 0x036a1): (207, "SmallOrderedHashMapMap"),
("MAP_SPACE", 0x036f1): (208, "SmallOrderedHashSetMap"),
("MAP_SPACE", 0x03741): (186, "StringTableMap"),
("MAP_SPACE", 0x03791): (211, "WeakFixedArrayMap"),
("MAP_SPACE", 0x037e1): (106, "NativeSourceStringMap"),
("MAP_SPACE", 0x03831): (64, "StringMap"),
("MAP_SPACE", 0x03881): (73, "ConsOneByteStringMap"),
@ -259,8 +260,8 @@ KNOWN_MAPS = {
("MAP_SPACE", 0x040f1): (147, "FixedUint8ClampedArrayMap"),
("MAP_SPACE", 0x04141): (149, "FixedBigUint64ArrayMap"),
("MAP_SPACE", 0x04191): (148, "FixedBigInt64ArrayMap"),
("MAP_SPACE", 0x041e1): (172, "Tuple2Map"),
("MAP_SPACE", 0x04231): (170, "ScriptMap"),
("MAP_SPACE", 0x041e1): (173, "Tuple2Map"),
("MAP_SPACE", 0x04231): (171, "ScriptMap"),
("MAP_SPACE", 0x04281): (163, "InterceptorInfoMap"),
("MAP_SPACE", 0x042d1): (154, "AccessorInfoMap"),
("MAP_SPACE", 0x04321): (153, "AccessCheckInfoMap"),
@ -272,22 +273,23 @@ KNOWN_MAPS = {
("MAP_SPACE", 0x04501): (160, "ContextExtensionMap"),
("MAP_SPACE", 0x04551): (161, "DebugInfoMap"),
("MAP_SPACE", 0x045a1): (162, "FunctionTemplateInfoMap"),
("MAP_SPACE", 0x045f1): (164, "ModuleInfoEntryMap"),
("MAP_SPACE", 0x04641): (165, "ModuleMap"),
("MAP_SPACE", 0x04691): (166, "ObjectTemplateInfoMap"),
("MAP_SPACE", 0x046e1): (167, "PromiseCapabilityMap"),
("MAP_SPACE", 0x04731): (168, "PromiseReactionMap"),
("MAP_SPACE", 0x04781): (169, "PrototypeInfoMap"),
("MAP_SPACE", 0x047d1): (171, "StackFrameInfoMap"),
("MAP_SPACE", 0x04821): (173, "Tuple3Map"),
("MAP_SPACE", 0x04871): (174, "WasmCompiledModuleMap"),
("MAP_SPACE", 0x048c1): (175, "WasmDebugInfoMap"),
("MAP_SPACE", 0x04911): (176, "WasmSharedModuleDataMap"),
("MAP_SPACE", 0x04961): (177, "CallableTaskMap"),
("MAP_SPACE", 0x049b1): (178, "CallbackTaskMap"),
("MAP_SPACE", 0x04a01): (179, "PromiseFulfillReactionJobTaskMap"),
("MAP_SPACE", 0x04a51): (180, "PromiseRejectReactionJobTaskMap"),
("MAP_SPACE", 0x04aa1): (181, "PromiseResolveThenableJobTaskMap"),
("MAP_SPACE", 0x045f1): (164, "InterpreterDataMap"),
("MAP_SPACE", 0x04641): (165, "ModuleInfoEntryMap"),
("MAP_SPACE", 0x04691): (166, "ModuleMap"),
("MAP_SPACE", 0x046e1): (167, "ObjectTemplateInfoMap"),
("MAP_SPACE", 0x04731): (168, "PromiseCapabilityMap"),
("MAP_SPACE", 0x04781): (169, "PromiseReactionMap"),
("MAP_SPACE", 0x047d1): (170, "PrototypeInfoMap"),
("MAP_SPACE", 0x04821): (172, "StackFrameInfoMap"),
("MAP_SPACE", 0x04871): (174, "Tuple3Map"),
("MAP_SPACE", 0x048c1): (175, "WasmCompiledModuleMap"),
("MAP_SPACE", 0x04911): (176, "WasmDebugInfoMap"),
("MAP_SPACE", 0x04961): (177, "WasmSharedModuleDataMap"),
("MAP_SPACE", 0x049b1): (178, "CallableTaskMap"),
("MAP_SPACE", 0x04a01): (179, "CallbackTaskMap"),
("MAP_SPACE", 0x04a51): (180, "PromiseFulfillReactionJobTaskMap"),
("MAP_SPACE", 0x04aa1): (181, "PromiseRejectReactionJobTaskMap"),
("MAP_SPACE", 0x04af1): (182, "PromiseResolveThenableJobTaskMap"),
}
# List of known V8 objects.