Revert "[Interpreter] Transition JSFunctions to call optimized code when possible."
This reverts commit ec619cbd89
.
Reason for revert: Crashing on Canary
BUG=chromium:718891
Original change's description:
> [Interpreter] Transition JSFunctions to call optimized code when possible.
>
> Now that the optimized code hangs off the feedback vector, it is possible
> to check whether a function has optimized code available every time it's
> called in the interpreter entry trampoline. If optimized code exists, the
> interpreter entry trampoline 'self-heals' the closure to point to the
> optimized code and links the closure into the optimized code list.
>
> BUG=v8:6246
>
> Change-Id: If1bd7c555bb0551bfe04b36baa6bcf949604717e
> Reviewed-on: https://chromium-review.googlesource.com/488026
> Reviewed-by: Michael Stanton <mvstanton@chromium.org>
> Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#45103}
TBR=rmcilroy@chromium.org,mvstanton@chromium.org
# Not skipping CQ checks because original CL landed > 1 day ago.
BUG=v8:6246
Change-Id: Ibda719be90fddf1d116c03a2a0c3018bcbe76018
Reviewed-on: https://chromium-review.googlesource.com/498632
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45169}
This commit is contained in:
parent
aad342d55b
commit
ce899dfdf3
@ -929,38 +929,6 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
|
||||
Generate_JSEntryTrampolineHelper(masm, true);
|
||||
}
|
||||
|
||||
static void ReplaceClosureEntryWithOptimizedCode(
|
||||
MacroAssembler* masm, Register optimized_code_entry, Register closure,
|
||||
Register scratch1, Register scratch2, Register scratch3) {
|
||||
Register native_context = scratch1;
|
||||
|
||||
// Store code entry in the closure.
|
||||
__ add(optimized_code_entry, optimized_code_entry,
|
||||
Operand(Code::kHeaderSize - kHeapObjectTag));
|
||||
__ str(optimized_code_entry,
|
||||
FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
|
||||
__ RecordWriteCodeEntryField(closure, optimized_code_entry, scratch2);
|
||||
|
||||
// Link the closure into the optimized function list.
|
||||
__ ldr(native_context, NativeContextMemOperand());
|
||||
__ ldr(scratch2,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ str(scratch2,
|
||||
FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset));
|
||||
__ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, scratch2,
|
||||
scratch3, kLRHasNotBeenSaved, kDontSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||
const int function_list_offset =
|
||||
Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
|
||||
__ str(closure,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
// Save closure before the write barrier.
|
||||
__ mov(scratch2, closure);
|
||||
__ RecordWriteContextSlot(native_context, function_list_offset, closure,
|
||||
scratch3, kLRHasNotBeenSaved, kDontSaveFPRegs);
|
||||
__ mov(closure, scratch2);
|
||||
}
|
||||
|
||||
static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch) {
|
||||
Register args_count = scratch;
|
||||
|
||||
@ -986,6 +954,7 @@ static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch) {
|
||||
// o r1: the JS function object being called.
|
||||
// o r3: the new target
|
||||
// o cp: our context
|
||||
// o pp: the caller's constant pool pointer (if enabled)
|
||||
// o fp: the caller's frame pointer
|
||||
// o sp: stack pointer
|
||||
// o lr: return address
|
||||
@ -1001,20 +970,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
FrameScope frame_scope(masm, StackFrame::MANUAL);
|
||||
__ PushStandardFrame(r1);
|
||||
|
||||
// First check if there is optimized code in the feedback vector which we
|
||||
// could call instead.
|
||||
Label switch_to_optimized_code;
|
||||
Register optimized_code_entry = r4;
|
||||
__ ldr(r0, FieldMemOperand(r1, JSFunction::kFeedbackVectorOffset));
|
||||
__ ldr(r0, FieldMemOperand(r0, Cell::kValueOffset));
|
||||
__ ldr(
|
||||
optimized_code_entry,
|
||||
FieldMemOperand(r0, FeedbackVector::kOptimizedCodeIndex * kPointerSize +
|
||||
FeedbackVector::kHeaderSize));
|
||||
__ ldr(optimized_code_entry,
|
||||
FieldMemOperand(optimized_code_entry, WeakCell::kValueOffset));
|
||||
__ JumpIfNotSmi(optimized_code_entry, &switch_to_optimized_code);
|
||||
|
||||
// Get the bytecode array from the function object (or from the DebugInfo if
|
||||
// it is present) and load it into kInterpreterBytecodeArrayRegister.
|
||||
__ ldr(r0, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
|
||||
@ -1127,15 +1082,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
__ str(r4, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
|
||||
__ RecordWriteCodeEntryField(r1, r4, r5);
|
||||
__ Jump(r4);
|
||||
|
||||
// If there is optimized code on the type feedback vector, get it into the
|
||||
// closure and link the closure into the optimized functions list, then call
|
||||
// the optimized code.
|
||||
__ bind(&switch_to_optimized_code);
|
||||
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
|
||||
ReplaceClosureEntryWithOptimizedCode(masm, optimized_code_entry, r1, r6, r5,
|
||||
r2);
|
||||
__ Jump(optimized_code_entry);
|
||||
}
|
||||
|
||||
static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
|
||||
@ -1392,8 +1338,31 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
__ ldr(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(entry, &try_shared);
|
||||
|
||||
// Store code entry in the closure and tail call.
|
||||
ReplaceClosureEntryWithOptimizedCode(masm, entry, closure, r6, r5, r2);
|
||||
// Store code entry in the closure.
|
||||
__ add(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
|
||||
__ str(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
|
||||
__ RecordWriteCodeEntryField(closure, entry, r5);
|
||||
|
||||
// Load native context into r6.
|
||||
Register native_context = r6;
|
||||
__ ldr(native_context, NativeContextMemOperand());
|
||||
|
||||
// Link the closure into the optimized function list.
|
||||
__ ldr(r5,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ str(r5, FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset));
|
||||
__ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, r5, r2,
|
||||
kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
|
||||
OMIT_SMI_CHECK);
|
||||
const int function_list_offset =
|
||||
Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
|
||||
__ str(closure,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
// Save closure before the write barrier.
|
||||
__ mov(r5, closure);
|
||||
__ RecordWriteContextSlot(native_context, function_list_offset, closure, r2,
|
||||
kLRHasNotBeenSaved, kDontSaveFPRegs);
|
||||
__ mov(closure, r5);
|
||||
__ Jump(entry);
|
||||
|
||||
// We found no optimized code.
|
||||
|
@ -945,36 +945,6 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
|
||||
Generate_JSEntryTrampolineHelper(masm, true);
|
||||
}
|
||||
|
||||
static void ReplaceClosureEntryWithOptimizedCode(
|
||||
MacroAssembler* masm, Register optimized_code_entry, Register closure,
|
||||
Register scratch1, Register scratch2, Register scratch3) {
|
||||
Register native_context = scratch1;
|
||||
|
||||
// Store code entry in the closure.
|
||||
__ Add(optimized_code_entry, optimized_code_entry,
|
||||
Operand(Code::kHeaderSize - kHeapObjectTag));
|
||||
__ Str(optimized_code_entry,
|
||||
FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
|
||||
__ RecordWriteCodeEntryField(closure, optimized_code_entry, scratch2);
|
||||
|
||||
// Link the closure into the optimized function list.
|
||||
__ Ldr(native_context, NativeContextMemOperand());
|
||||
__ Ldr(scratch2,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ Str(scratch2,
|
||||
FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset));
|
||||
__ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, scratch2,
|
||||
scratch3, kLRHasNotBeenSaved, kDontSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||
const int function_list_offset =
|
||||
Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
|
||||
__ Str(closure,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ Mov(scratch2, closure);
|
||||
__ RecordWriteContextSlot(native_context, function_list_offset, scratch2,
|
||||
scratch3, kLRHasNotBeenSaved, kDontSaveFPRegs);
|
||||
}
|
||||
|
||||
static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch) {
|
||||
Register args_count = scratch;
|
||||
|
||||
@ -1016,20 +986,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
__ Push(lr, fp, cp, x1);
|
||||
__ Add(fp, jssp, StandardFrameConstants::kFixedFrameSizeFromFp);
|
||||
|
||||
// First check if there is optimized code in the feedback vector which we
|
||||
// could call instead.
|
||||
Label switch_to_optimized_code;
|
||||
Register optimized_code_entry = x7;
|
||||
__ Ldr(x0, FieldMemOperand(x1, JSFunction::kFeedbackVectorOffset));
|
||||
__ Ldr(x0, FieldMemOperand(x0, Cell::kValueOffset));
|
||||
__ Ldr(
|
||||
optimized_code_entry,
|
||||
FieldMemOperand(x0, FeedbackVector::kOptimizedCodeIndex * kPointerSize +
|
||||
FeedbackVector::kHeaderSize));
|
||||
__ Ldr(optimized_code_entry,
|
||||
FieldMemOperand(optimized_code_entry, WeakCell::kValueOffset));
|
||||
__ JumpIfNotSmi(optimized_code_entry, &switch_to_optimized_code);
|
||||
|
||||
// Get the bytecode array from the function object (or from the DebugInfo if
|
||||
// it is present) and load it into kInterpreterBytecodeArrayRegister.
|
||||
__ Ldr(x0, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
|
||||
@ -1145,15 +1101,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
__ Str(x7, FieldMemOperand(x1, JSFunction::kCodeEntryOffset));
|
||||
__ RecordWriteCodeEntryField(x1, x7, x5);
|
||||
__ Jump(x7);
|
||||
|
||||
// If there is optimized code on the type feedback vector, get it into the
|
||||
// closure and link the closure into the optimized functions list, then call
|
||||
// the optimized code.
|
||||
__ bind(&switch_to_optimized_code);
|
||||
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
|
||||
ReplaceClosureEntryWithOptimizedCode(masm, optimized_code_entry, x1, x4, x5,
|
||||
x13);
|
||||
__ Jump(optimized_code_entry);
|
||||
}
|
||||
|
||||
static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
|
||||
@ -1416,8 +1363,29 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
__ Ldr(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(entry, &try_shared);
|
||||
|
||||
// Found code. Get it into the closure and tail call.
|
||||
ReplaceClosureEntryWithOptimizedCode(masm, entry, closure, x4, x5, x13);
|
||||
// Found code. Get it into the closure and return.
|
||||
__ Add(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
|
||||
__ Str(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
|
||||
__ RecordWriteCodeEntryField(closure, entry, x5);
|
||||
|
||||
// Load native context into x4.
|
||||
Register native_context = x4;
|
||||
__ Ldr(native_context, NativeContextMemOperand());
|
||||
|
||||
// Link the closure into the optimized function list.
|
||||
__ Ldr(x8,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ Str(x8, FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset));
|
||||
__ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, x8, x13,
|
||||
kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
|
||||
OMIT_SMI_CHECK);
|
||||
const int function_list_offset =
|
||||
Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
|
||||
__ Str(closure,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ Mov(x5, closure);
|
||||
__ RecordWriteContextSlot(native_context, function_list_offset, x5, x13,
|
||||
kLRHasNotBeenSaved, kDontSaveFPRegs);
|
||||
__ Jump(entry);
|
||||
|
||||
// We found no optimized code.
|
||||
|
@ -561,37 +561,6 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
|
||||
__ jmp(&stepping_prepared);
|
||||
}
|
||||
|
||||
static void ReplaceClosureEntryWithOptimizedCode(
|
||||
MacroAssembler* masm, Register optimized_code_entry, Register closure,
|
||||
Register scratch1, Register scratch2, Register scratch3) {
|
||||
Register native_context = scratch1;
|
||||
|
||||
// Store the optimized code in the closure.
|
||||
__ lea(optimized_code_entry,
|
||||
FieldOperand(optimized_code_entry, Code::kHeaderSize));
|
||||
__ mov(FieldOperand(closure, JSFunction::kCodeEntryOffset),
|
||||
optimized_code_entry);
|
||||
__ RecordWriteCodeEntryField(closure, optimized_code_entry, scratch2);
|
||||
|
||||
// Link the closure into the optimized function list.
|
||||
__ mov(native_context, NativeContextOperand());
|
||||
__ mov(scratch3,
|
||||
ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ mov(FieldOperand(closure, JSFunction::kNextFunctionLinkOffset), scratch3);
|
||||
__ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, scratch3,
|
||||
scratch2, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
|
||||
OMIT_SMI_CHECK);
|
||||
const int function_list_offset =
|
||||
Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
|
||||
__ mov(ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST),
|
||||
closure);
|
||||
// Save closure before the write barrier.
|
||||
__ mov(scratch3, closure);
|
||||
__ RecordWriteContextSlot(native_context, function_list_offset, closure,
|
||||
scratch2, kDontSaveFPRegs);
|
||||
__ mov(closure, scratch3);
|
||||
}
|
||||
|
||||
static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch1,
|
||||
Register scratch2) {
|
||||
Register args_count = scratch1;
|
||||
@ -639,19 +608,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
__ push(edi); // Callee's JS function.
|
||||
__ push(edx); // Callee's new target.
|
||||
|
||||
// First check if there is optimized code in the feedback vector which we
|
||||
// could call instead.
|
||||
Label switch_to_optimized_code;
|
||||
Register optimized_code_entry = ecx;
|
||||
__ mov(ebx, FieldOperand(edi, JSFunction::kFeedbackVectorOffset));
|
||||
__ mov(ebx, FieldOperand(ebx, Cell::kValueOffset));
|
||||
__ mov(optimized_code_entry,
|
||||
FieldOperand(ebx, FeedbackVector::kOptimizedCodeIndex * kPointerSize +
|
||||
FeedbackVector::kHeaderSize));
|
||||
__ mov(optimized_code_entry,
|
||||
FieldOperand(optimized_code_entry, WeakCell::kValueOffset));
|
||||
__ JumpIfNotSmi(optimized_code_entry, &switch_to_optimized_code);
|
||||
|
||||
// Get the bytecode array from the function object (or from the DebugInfo if
|
||||
// it is present) and load it into kInterpreterBytecodeArrayRegister.
|
||||
__ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
|
||||
@ -768,17 +724,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
__ mov(FieldOperand(edi, JSFunction::kCodeEntryOffset), ecx);
|
||||
__ RecordWriteCodeEntryField(edi, ecx, ebx);
|
||||
__ jmp(ecx);
|
||||
|
||||
// If there is optimized code on the type feedback vector, get it into the
|
||||
// closure and link the closure into the optimized functions list, then call
|
||||
// the optimized code.
|
||||
__ bind(&switch_to_optimized_code);
|
||||
__ push(edx);
|
||||
ReplaceClosureEntryWithOptimizedCode(masm, optimized_code_entry, edi, edx,
|
||||
eax, ebx);
|
||||
__ pop(edx);
|
||||
__ leave();
|
||||
__ jmp(optimized_code_entry);
|
||||
}
|
||||
|
||||
static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
|
||||
@ -1176,10 +1121,32 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
__ mov(entry, FieldOperand(entry, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(entry, &try_shared);
|
||||
|
||||
// Store code entry in the closure and tail call.
|
||||
// Store code entry in the closure.
|
||||
__ lea(entry, FieldOperand(entry, Code::kHeaderSize));
|
||||
__ mov(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry);
|
||||
__ push(argument_count);
|
||||
__ push(new_target);
|
||||
ReplaceClosureEntryWithOptimizedCode(masm, entry, closure, edx, eax, ebx);
|
||||
__ RecordWriteCodeEntryField(closure, entry, eax);
|
||||
|
||||
// Load native context into edx.
|
||||
Register native_context = edx;
|
||||
__ mov(native_context, NativeContextOperand());
|
||||
|
||||
// Link the closure into the optimized function list.
|
||||
__ mov(ebx,
|
||||
ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ mov(FieldOperand(closure, JSFunction::kNextFunctionLinkOffset), ebx);
|
||||
__ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, ebx, eax,
|
||||
kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||
const int function_list_offset =
|
||||
Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
|
||||
__ mov(ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST),
|
||||
closure);
|
||||
// Save closure before the write barrier.
|
||||
__ mov(ebx, closure);
|
||||
__ RecordWriteContextSlot(native_context, function_list_offset, closure, eax,
|
||||
kDontSaveFPRegs);
|
||||
__ mov(closure, ebx);
|
||||
__ pop(new_target);
|
||||
__ pop(argument_count);
|
||||
__ jmp(entry);
|
||||
|
@ -918,38 +918,6 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
|
||||
__ lw(t0, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
|
||||
}
|
||||
|
||||
static void ReplaceClosureEntryWithOptimizedCode(
|
||||
MacroAssembler* masm, Register optimized_code_entry, Register closure,
|
||||
Register scratch1, Register scratch2, Register scratch3) {
|
||||
Register native_context = scratch1;
|
||||
|
||||
// Store code entry in the closure.
|
||||
__ Addu(optimized_code_entry, optimized_code_entry,
|
||||
Operand(Code::kHeaderSize - kHeapObjectTag));
|
||||
__ sw(optimized_code_entry,
|
||||
FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
|
||||
__ RecordWriteCodeEntryField(closure, optimized_code_entry, scratch2);
|
||||
|
||||
// Link the closure into the optimized function list.
|
||||
__ lw(native_context, NativeContextMemOperand());
|
||||
__ lw(scratch2,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ sw(scratch2,
|
||||
FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset));
|
||||
__ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, scratch2,
|
||||
scratch3, kRAHasNotBeenSaved, kDontSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||
const int function_list_offset =
|
||||
Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
|
||||
__ sw(closure,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
// Save closure before the write barrier.
|
||||
__ mov(scratch2, closure);
|
||||
__ RecordWriteContextSlot(native_context, function_list_offset, closure,
|
||||
scratch3, kRAHasNotBeenSaved, kDontSaveFPRegs);
|
||||
__ mov(closure, scratch2);
|
||||
}
|
||||
|
||||
static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch) {
|
||||
Register args_count = scratch;
|
||||
|
||||
@ -990,19 +958,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
FrameScope frame_scope(masm, StackFrame::MANUAL);
|
||||
__ PushStandardFrame(a1);
|
||||
|
||||
// First check if there is optimized code in the feedback vector which we
|
||||
// could call instead.
|
||||
Label switch_to_optimized_code;
|
||||
Register optimized_code_entry = t0;
|
||||
__ lw(a0, FieldMemOperand(a1, JSFunction::kFeedbackVectorOffset));
|
||||
__ lw(a0, FieldMemOperand(a0, Cell::kValueOffset));
|
||||
__ lw(optimized_code_entry,
|
||||
FieldMemOperand(a0, FeedbackVector::kOptimizedCodeIndex * kPointerSize +
|
||||
FeedbackVector::kHeaderSize));
|
||||
__ lw(optimized_code_entry,
|
||||
FieldMemOperand(optimized_code_entry, WeakCell::kValueOffset));
|
||||
__ JumpIfNotSmi(optimized_code_entry, &switch_to_optimized_code);
|
||||
|
||||
// Get the bytecode array from the function object (or from the DebugInfo if
|
||||
// it is present) and load it into kInterpreterBytecodeArrayRegister.
|
||||
__ lw(a0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
|
||||
@ -1121,15 +1076,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
__ sw(t0, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
|
||||
__ RecordWriteCodeEntryField(a1, t0, t1);
|
||||
__ Jump(t0);
|
||||
|
||||
// If there is optimized code on the type feedback vector, get it into the
|
||||
// closure and link the closure into the optimized functions list, then call
|
||||
// the optimized code.
|
||||
__ bind(&switch_to_optimized_code);
|
||||
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
|
||||
ReplaceClosureEntryWithOptimizedCode(masm, optimized_code_entry, a1, t3, t1,
|
||||
t2);
|
||||
__ Jump(optimized_code_entry);
|
||||
}
|
||||
|
||||
static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
|
||||
@ -1389,8 +1335,31 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
__ lw(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(entry, &try_shared);
|
||||
|
||||
// Store code entry in the closure and tail call.
|
||||
ReplaceClosureEntryWithOptimizedCode(masm, entry, closure, t3, t1, t2);
|
||||
// Store code entry in the closure.
|
||||
__ Addu(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
|
||||
__ sw(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
|
||||
__ RecordWriteCodeEntryField(closure, entry, t1);
|
||||
|
||||
// Load native context into t3.
|
||||
Register native_context = t3;
|
||||
__ lw(native_context, NativeContextMemOperand());
|
||||
|
||||
// Link the closure into the optimized function list.
|
||||
__ lw(t1,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ sw(t1, FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset));
|
||||
__ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, t1, t2,
|
||||
kRAHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
|
||||
OMIT_SMI_CHECK);
|
||||
const int function_list_offset =
|
||||
Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
|
||||
__ sw(closure,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
// Save closure before the write barrier.
|
||||
__ mov(t1, closure);
|
||||
__ RecordWriteContextSlot(native_context, function_list_offset, closure, t2,
|
||||
kRAHasNotBeenSaved, kDontSaveFPRegs);
|
||||
__ mov(closure, t1);
|
||||
__ Jump(entry);
|
||||
|
||||
// We found no optimized code.
|
||||
|
@ -914,38 +914,6 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
|
||||
Generate_JSEntryTrampolineHelper(masm, true);
|
||||
}
|
||||
|
||||
static void ReplaceClosureEntryWithOptimizedCode(
|
||||
MacroAssembler* masm, Register optimized_code_entry, Register closure,
|
||||
Register scratch1, Register scratch2, Register scratch3) {
|
||||
Register native_context = scratch1;
|
||||
|
||||
// Store code entry in the closure.
|
||||
__ Daddu(optimized_code_entry, optimized_code_entry,
|
||||
Operand(Code::kHeaderSize - kHeapObjectTag));
|
||||
__ Sd(optimized_code_entry,
|
||||
FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
|
||||
__ RecordWriteCodeEntryField(closure, optimized_code_entry, scratch2);
|
||||
|
||||
// Link the closure into the optimized function list.
|
||||
__ Ld(native_context, NativeContextMemOperand());
|
||||
__ Ld(scratch2,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ Sd(scratch2,
|
||||
FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset));
|
||||
__ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, scratch2,
|
||||
scratch3, kRAHasNotBeenSaved, kDontSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||
const int function_list_offset =
|
||||
Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
|
||||
__ Sd(closure,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
// Save closure before the write barrier.
|
||||
__ mov(scratch2, closure);
|
||||
__ RecordWriteContextSlot(native_context, function_list_offset, closure,
|
||||
scratch3, kRAHasNotBeenSaved, kDontSaveFPRegs);
|
||||
__ mov(closure, scratch2);
|
||||
}
|
||||
|
||||
static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch) {
|
||||
Register args_count = scratch;
|
||||
|
||||
@ -985,19 +953,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
FrameScope frame_scope(masm, StackFrame::MANUAL);
|
||||
__ PushStandardFrame(a1);
|
||||
|
||||
// First check if there is optimized code in the feedback vector which we
|
||||
// could call instead.
|
||||
Label switch_to_optimized_code;
|
||||
Register optimized_code_entry = a4;
|
||||
__ Ld(a0, FieldMemOperand(a1, JSFunction::kFeedbackVectorOffset));
|
||||
__ Ld(a0, FieldMemOperand(a0, Cell::kValueOffset));
|
||||
__ Ld(optimized_code_entry,
|
||||
FieldMemOperand(a0, FeedbackVector::kOptimizedCodeIndex * kPointerSize +
|
||||
FeedbackVector::kHeaderSize));
|
||||
__ Ld(optimized_code_entry,
|
||||
FieldMemOperand(optimized_code_entry, WeakCell::kValueOffset));
|
||||
__ JumpIfNotSmi(optimized_code_entry, &switch_to_optimized_code);
|
||||
|
||||
// Get the bytecode array from the function object (or from the DebugInfo if
|
||||
// it is present) and load it into kInterpreterBytecodeArrayRegister.
|
||||
__ Ld(a0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
|
||||
@ -1116,15 +1071,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
__ Sd(a4, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
|
||||
__ RecordWriteCodeEntryField(a1, a4, a5);
|
||||
__ Jump(a4);
|
||||
|
||||
// If there is optimized code on the type feedback vector, get it into the
|
||||
// closure and link the closure into the optimized functions list, then call
|
||||
// the optimized code.
|
||||
__ bind(&switch_to_optimized_code);
|
||||
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
|
||||
ReplaceClosureEntryWithOptimizedCode(masm, optimized_code_entry, a1, t3, a5,
|
||||
t0);
|
||||
__ Jump(optimized_code_entry);
|
||||
}
|
||||
|
||||
static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
|
||||
@ -1385,8 +1331,31 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
__ Ld(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(entry, &try_shared);
|
||||
|
||||
// Found code. Get it into the closure and tail call.
|
||||
ReplaceClosureEntryWithOptimizedCode(masm, entry, closure, t3, a5, t0);
|
||||
// Found code. Get it into the closure and return.
|
||||
__ Daddu(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
|
||||
__ Sd(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
|
||||
__ RecordWriteCodeEntryField(closure, entry, a5);
|
||||
|
||||
// Load native context into t3.
|
||||
Register native_context = t3;
|
||||
__ Ld(native_context, NativeContextMemOperand());
|
||||
|
||||
// Link the closure into the optimized function list.
|
||||
__ Ld(a5,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ Sd(a5, FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset));
|
||||
__ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, a5, t0,
|
||||
kRAHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
|
||||
OMIT_SMI_CHECK);
|
||||
const int function_list_offset =
|
||||
Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
|
||||
__ Sd(closure,
|
||||
ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
// Save closure before the write barrier.
|
||||
__ mov(a5, closure);
|
||||
__ RecordWriteContextSlot(native_context, function_list_offset, closure, t0,
|
||||
kRAHasNotBeenSaved, kDontSaveFPRegs);
|
||||
__ mov(closure, a5);
|
||||
__ Jump(entry);
|
||||
|
||||
// We found no optimized code.
|
||||
|
@ -641,37 +641,6 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
|
||||
__ jmp(&stepping_prepared);
|
||||
}
|
||||
|
||||
static void ReplaceClosureEntryWithOptimizedCode(
|
||||
MacroAssembler* masm, Register optimized_code_entry, Register closure,
|
||||
Register scratch1, Register scratch2, Register scratch3) {
|
||||
Register native_context = scratch1;
|
||||
|
||||
// Store the optimized code in the closure.
|
||||
__ leap(optimized_code_entry,
|
||||
FieldOperand(optimized_code_entry, Code::kHeaderSize));
|
||||
__ movp(FieldOperand(closure, JSFunction::kCodeEntryOffset),
|
||||
optimized_code_entry);
|
||||
__ RecordWriteCodeEntryField(closure, optimized_code_entry, scratch2);
|
||||
|
||||
// Link the closure into the optimized function list.
|
||||
__ movp(native_context, NativeContextOperand());
|
||||
__ movp(scratch3,
|
||||
ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ movp(FieldOperand(closure, JSFunction::kNextFunctionLinkOffset), scratch3);
|
||||
__ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, scratch3,
|
||||
scratch2, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
|
||||
OMIT_SMI_CHECK);
|
||||
const int function_list_offset =
|
||||
Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
|
||||
__ movp(ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST),
|
||||
closure);
|
||||
// Save closure before the write barrier.
|
||||
__ movp(scratch3, closure);
|
||||
__ RecordWriteContextSlot(native_context, function_list_offset, closure,
|
||||
scratch2, kDontSaveFPRegs);
|
||||
__ movp(closure, scratch3);
|
||||
}
|
||||
|
||||
static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch1,
|
||||
Register scratch2) {
|
||||
Register args_count = scratch1;
|
||||
@ -719,18 +688,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
__ Push(rdi); // Callee's JS function.
|
||||
__ Push(rdx); // Callee's new target.
|
||||
|
||||
// First check if there is optimized code in the feedback vector which we
|
||||
// could call instead.
|
||||
Label switch_to_optimized_code;
|
||||
Register optimized_code_entry = rcx;
|
||||
__ movp(rbx, FieldOperand(rdi, JSFunction::kFeedbackVectorOffset));
|
||||
__ movp(rbx, FieldOperand(rbx, Cell::kValueOffset));
|
||||
__ movp(rbx,
|
||||
FieldOperand(rbx, FeedbackVector::kOptimizedCodeIndex * kPointerSize +
|
||||
FeedbackVector::kHeaderSize));
|
||||
__ movp(optimized_code_entry, FieldOperand(rbx, WeakCell::kValueOffset));
|
||||
__ JumpIfNotSmi(optimized_code_entry, &switch_to_optimized_code);
|
||||
|
||||
// Get the bytecode array from the function object (or from the DebugInfo if
|
||||
// it is present) and load it into kInterpreterBytecodeArrayRegister.
|
||||
__ movp(rax, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
|
||||
@ -845,15 +802,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
__ movp(FieldOperand(rdi, JSFunction::kCodeEntryOffset), rcx);
|
||||
__ RecordWriteCodeEntryField(rdi, rcx, r15);
|
||||
__ jmp(rcx);
|
||||
|
||||
// If there is optimized code on the type feedback vector, get it into the
|
||||
// closure and link the closure into the optimized functions list, then call
|
||||
// the optimized code.
|
||||
__ bind(&switch_to_optimized_code);
|
||||
__ leave();
|
||||
ReplaceClosureEntryWithOptimizedCode(masm, optimized_code_entry, rdi, r14,
|
||||
r15, rbx);
|
||||
__ jmp(optimized_code_entry);
|
||||
}
|
||||
|
||||
static void Generate_StackOverflowCheck(
|
||||
@ -1150,8 +1098,30 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
__ movp(entry, FieldOperand(entry, WeakCell::kValueOffset));
|
||||
__ JumpIfSmi(entry, &try_shared);
|
||||
|
||||
// Found code. Get it into the closure and tail call it.
|
||||
ReplaceClosureEntryWithOptimizedCode(masm, entry, closure, r14, r15, rbx);
|
||||
// Found code. Get it into the closure and return.
|
||||
__ leap(entry, FieldOperand(entry, Code::kHeaderSize));
|
||||
__ movp(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry);
|
||||
__ RecordWriteCodeEntryField(closure, entry, r15);
|
||||
|
||||
// Load native context into r14.
|
||||
Register native_context = r14;
|
||||
__ movp(native_context, NativeContextOperand());
|
||||
|
||||
// Link the closure into the optimized function list.
|
||||
__ movp(rbx,
|
||||
ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
|
||||
__ movp(FieldOperand(closure, JSFunction::kNextFunctionLinkOffset), rbx);
|
||||
__ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, rbx, r15,
|
||||
kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||
const int function_list_offset =
|
||||
Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
|
||||
__ movp(ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST),
|
||||
closure);
|
||||
// Save closure before the write barrier.
|
||||
__ movp(rbx, closure);
|
||||
__ RecordWriteContextSlot(native_context, function_list_offset, closure, r15,
|
||||
kDontSaveFPRegs);
|
||||
__ movp(closure, rbx);
|
||||
__ jmp(entry);
|
||||
|
||||
// We found no optimized code.
|
||||
|
Loading…
Reference in New Issue
Block a user