Commit e67420cb authored by jgruber's avatar jgruber Committed by Commit Bot

[builtins] Move DeserializeLazy to ASM

There are two main reasons to move DeserializeLazy to ASM:

1. We avoid complications around the distinction between Call/Construct
   cases by making sure relevant registers (e.g. new_target) remain
   unclobbered.

2. We can avoid the tail-call through CodeFactory::Call/Construct by
   jumping directly to the deserialized code object.

Bug: v8:6624
Change-Id: Idef8fa73d804e16d510f62766c735d1891729b81
Reviewed-on: https://chromium-review.googlesource.com/652472Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47876}
parent f82ae284
......@@ -1613,6 +1613,95 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
}
// Lazy deserialization design doc: http://goo.gl/dxkYDZ.
void Builtins::Generate_DeserializeLazy(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : argument count (preserved for callee)
// -- r3 : new target (preserved for callee)
// -- r1 : target function (preserved for callee)
// -----------------------------------
Label deserialize_in_runtime;
Register target = r1; // Must be preserved
Register scratch0 = r2;
Register scratch1 = r4;
CHECK(!scratch0.is(r0) && !scratch0.is(r3) && !scratch0.is(r1));
CHECK(!scratch1.is(r0) && !scratch1.is(r3) && !scratch1.is(r1));
CHECK(!scratch0.is(scratch1));
// Load the builtin id for lazy deserialization from SharedFunctionInfo.
__ AssertFunction(target);
__ ldr(scratch0,
FieldMemOperand(target, JSFunction::kSharedFunctionInfoOffset));
__ ldr(scratch1,
FieldMemOperand(scratch0, SharedFunctionInfo::kFunctionDataOffset));
__ AssertSmi(scratch1);
// The builtin may already have been deserialized. If that is the case, it is
// stored in the builtins table, and we can copy to correct code object to
// both the shared function info and function without calling into runtime.
//
// Otherwise, we need to call into runtime to deserialize.
{
// Load the code object at builtins_table[builtin_id] into scratch1.
__ SmiUntag(scratch1);
__ Move(scratch0,
Operand(ExternalReference::builtins_address(masm->isolate())));
__ ldr(scratch1, MemOperand(scratch0, scratch1, LSL, kPointerSizeLog2));
// Check if the loaded code object has already been deserialized. This is
// the case iff it does not equal DeserializeLazy.
__ Move(scratch0, masm->CodeObject());
__ cmp(scratch1, scratch0);
__ b(eq, &deserialize_in_runtime);
}
{
// If we've reached this spot, the target builtin has been deserialized and
// we simply need to copy it over. First to the shared function info.
Register target_builtin = scratch1;
Register shared = scratch0;
__ ldr(shared,
FieldMemOperand(target, JSFunction::kSharedFunctionInfoOffset));
CHECK(!r5.is(target) && !r5.is(scratch0) && !r5.is(scratch1));
CHECK(!r9.is(target) && !r9.is(scratch0) && !r9.is(scratch1));
__ str(target_builtin,
FieldMemOperand(shared, SharedFunctionInfo::kCodeOffset));
__ mov(r9, target_builtin); // Write barrier clobbers r9 below.
__ RecordWriteField(shared, SharedFunctionInfo::kCodeOffset, r9, r5,
kLRHasNotBeenSaved, kDontSaveFPRegs,
OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
// And second to the target function.
__ str(target_builtin, FieldMemOperand(target, JSFunction::kCodeOffset));
__ mov(r9, target_builtin); // Write barrier clobbers r9 below.
__ RecordWriteField(target, JSFunction::kCodeOffset, r9, r5,
kLRHasNotBeenSaved, kDontSaveFPRegs,
OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
// All copying is done. Jump to the deserialized code object.
__ add(target_builtin, target_builtin,
Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(target_builtin);
}
__ bind(&deserialize_in_runtime);
GenerateTailCallToReturnedCode(masm, Runtime::kDeserializeLazy);
}
void Builtins::Generate_InstantiateAsmJs(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : argument count (preserved for callee)
......
......@@ -1632,6 +1632,94 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
}
// Lazy deserialization design doc: http://goo.gl/dxkYDZ.
void Builtins::Generate_DeserializeLazy(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : argument count (preserved for callee)
// -- x3 : new target (preserved for callee)
// -- x1 : target function (preserved for callee)
// -----------------------------------
Label deserialize_in_runtime;
Register target = x1; // Must be preserved
Register scratch0 = x2;
Register scratch1 = x4;
CHECK(!scratch0.is(x0) && !scratch0.is(x3) && !scratch0.is(x1));
CHECK(!scratch1.is(x0) && !scratch1.is(x3) && !scratch1.is(x1));
CHECK(!scratch0.is(scratch1));
// Load the builtin id for lazy deserialization from SharedFunctionInfo.
__ AssertFunction(target);
__ Ldr(scratch0,
FieldMemOperand(target, JSFunction::kSharedFunctionInfoOffset));
__ Ldr(scratch1,
FieldMemOperand(scratch0, SharedFunctionInfo::kFunctionDataOffset));
__ AssertSmi(scratch1);
// The builtin may already have been deserialized. If that is the case, it is
// stored in the builtins table, and we can copy to correct code object to
// both the shared function info and function without calling into runtime.
//
// Otherwise, we need to call into runtime to deserialize.
{
// Load the code object at builtins_table[builtin_id] into scratch1.
__ SmiUntag(scratch1);
__ Mov(scratch0, ExternalReference::builtins_address(masm->isolate()));
__ Ldr(scratch1, MemOperand(scratch0, scratch1, LSL, kPointerSizeLog2));
// Check if the loaded code object has already been deserialized. This is
// the case iff it does not equal DeserializeLazy.
__ Move(scratch0, masm->CodeObject());
__ Cmp(scratch1, scratch0);
__ B(eq, &deserialize_in_runtime);
}
{
// If we've reached this spot, the target builtin has been deserialized and
// we simply need to copy it over. First to the shared function info.
Register target_builtin = scratch1;
Register shared = scratch0;
__ Ldr(shared,
FieldMemOperand(target, JSFunction::kSharedFunctionInfoOffset));
CHECK(!x5.is(target) && !x5.is(scratch0) && !x5.is(scratch1));
CHECK(!x9.is(target) && !x9.is(scratch0) && !x9.is(scratch1));
__ Str(target_builtin,
FieldMemOperand(shared, SharedFunctionInfo::kCodeOffset));
__ Mov(x9, target_builtin); // Write barrier clobbers x9 below.
__ RecordWriteField(shared, SharedFunctionInfo::kCodeOffset, x9, x5,
kLRHasNotBeenSaved, kDontSaveFPRegs,
OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
// And second to the target function.
__ Str(target_builtin, FieldMemOperand(target, JSFunction::kCodeOffset));
__ Mov(x9, target_builtin); // Write barrier clobbers x9 below.
__ RecordWriteField(target, JSFunction::kCodeOffset, x9, x5,
kLRHasNotBeenSaved, kDontSaveFPRegs,
OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
// All copying is done. Jump to the deserialized code object.
__ Add(target_builtin, target_builtin,
Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(target_builtin);
}
__ bind(&deserialize_in_runtime);
GenerateTailCallToReturnedCode(masm, Runtime::kDeserializeLazy);
}
void Builtins::Generate_InstantiateAsmJs(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : argument count (preserved for callee)
......
......@@ -122,7 +122,7 @@ namespace internal {
ASM(CompileLazy) \
ASM(CompileLazyDeoptimizedCode) \
ASM(CheckOptimizationMarker) \
TFJ(DeserializeLazy, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
ASM(DeserializeLazy) \
ASM(InstantiateAsmJs) \
ASM(NotifyDeoptimized) \
ASM(NotifySoftDeoptimized) \
......
......@@ -11,98 +11,6 @@
namespace v8 {
namespace internal {
// -----------------------------------------------------------------------------
// Lazy deserialization.
// DeserializeLazy is very similar to CompileLazy: it is called with the
// arguments intended for the target function. We load the function from the
// frame, make sure its code object is deserialized, then tail-call into it,
// passing along all arguments unmodified.
TF_BUILTIN(DeserializeLazy, CodeStubAssembler) {
Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
Node* context = Parameter(BuiltinDescriptor::kContext);
CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
Node* function = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
MachineType::TaggedPointer());
CSA_ASSERT(this, IsJSFunction(function));
Node* shared =
LoadObjectField(function, JSFunction::kSharedFunctionInfoOffset);
CSA_ASSERT(this, IsSharedFunctionInfo(shared));
// The shared function info stores the target builtin id that needs to be
// deserialized (originally set by Factory::NewSharedFunctionInfo).
Node* target_builtin_id =
LoadObjectField(shared, SharedFunctionInfo::kFunctionDataOffset);
CSA_ASSERT(this, TaggedIsSmi(target_builtin_id));
CSA_ASSERT(this, SmiNotEqual(target_builtin_id,
SmiConstant(Builtins::kDeserializeLazy)));
// The builtin may already have been deserialized. If that is the case, it is
// stored in the builtins table, and we can copy to correct code object to
// both the shared function info and function without calling into runtime.
//
// Otherwise, we need to call into runtime to deserialize.
Label copy_from_builtins_table(this), deserialize_in_runtime(this), out(this);
Node* code_object_in_table;
// Check what's in the builtins table.
{
Node* builtins_table =
ExternalConstant(ExternalReference::builtins_address(isolate()));
Node* builtin_ptr =
IntPtrAdd(UncheckedCast<IntPtrT>(builtins_table),
SmiUntag(SmiShl(target_builtin_id, kPointerSizeLog2)));
code_object_in_table = Load(MachineType::AnyTagged(), builtin_ptr);
CSA_ASSERT(this, IsCodeMap(LoadMap(code_object_in_table)));
Node* maybe_deserialized_builtin_id = LoadObjectField(
code_object_in_table, Code::kBuiltinIndexOffset, MachineType::Int32());
Branch(Word32Equal(maybe_deserialized_builtin_id,
Int32Constant(Builtins::kDeserializeLazy)),
&deserialize_in_runtime, &copy_from_builtins_table);
}
BIND(&copy_from_builtins_table);
{
CSA_ASSERT(this, SmiGreaterThanOrEqual(target_builtin_id, SmiConstant(0)));
CSA_ASSERT(this, SmiLessThan(target_builtin_id,
SmiConstant(Builtins::builtin_count)));
StoreObjectField(shared, SharedFunctionInfo::kCodeOffset,
code_object_in_table);
StoreObjectField(function, JSFunction::kCodeOffset, code_object_in_table);
Goto(&out);
}
BIND(&deserialize_in_runtime);
{
CallRuntime(Runtime::kDeserializeLazy, context, function);
#ifdef DEBUG
Node* function_code = LoadObjectField(function, JSFunction::kCodeOffset);
CSA_ASSERT(this, IsCodeMap(LoadMap(function_code)));
Node* function_code_builtin_id = LoadObjectField(
function_code, Code::kBuiltinIndexOffset, MachineType::Int32());
CSA_ASSERT(this, Word32Equal(function_code_builtin_id,
SmiToWord32(target_builtin_id)));
#endif
Goto(&out);
}
// Finally, tail-call into the deserialized code, passing along any existing
// arguments on the stack unmodified.
BIND(&out);
TailCallStub(CodeFactory::Call(isolate()), context, function, argc);
}
// -----------------------------------------------------------------------------
// Interrupt and stack checks.
......
......@@ -1391,6 +1391,92 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
}
// Lazy deserialization design doc: http://goo.gl/dxkYDZ.
void Builtins::Generate_DeserializeLazy(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : argument count (preserved for callee)
// -- edx : new target (preserved for callee)
// -- edi : target function (preserved for callee)
// -----------------------------------
Label deserialize_in_runtime;
Register target = edi; // Must be preserved
Register scratch0 = ebx;
Register scratch1 = ecx;
CHECK(!scratch0.is(eax) && !scratch0.is(edx) && !scratch0.is(edi));
CHECK(!scratch1.is(eax) && !scratch1.is(edx) && !scratch1.is(edi));
CHECK(!scratch0.is(scratch1));
// Load the builtin id for lazy deserialization from SharedFunctionInfo.
__ AssertFunction(target);
__ mov(scratch0, FieldOperand(target, JSFunction::kSharedFunctionInfoOffset));
__ mov(scratch1,
FieldOperand(scratch0, SharedFunctionInfo::kFunctionDataOffset));
__ AssertSmi(scratch1);
// The builtin may already have been deserialized. If that is the case, it is
// stored in the builtins table, and we can copy to correct code object to
// both the shared function info and function without calling into runtime.
//
// Otherwise, we need to call into runtime to deserialize.
{
// Load the code object at builtins_table[builtin_id] into scratch1.
__ SmiUntag(scratch1);
__ mov(scratch0,
Immediate(ExternalReference::builtins_address(masm->isolate())));
__ mov(scratch1, Operand(scratch0, scratch1, times_pointer_size, 0));
// Check if the loaded code object has already been deserialized. This is
// the case iff it does not equal DeserializeLazy.
__ Move(scratch0, masm->CodeObject());
__ cmp(scratch1, scratch0);
__ j(equal, &deserialize_in_runtime);
}
{
// If we've reached this spot, the target builtin has been deserialized and
// we simply need to copy it over. First to the shared function info.
Register target_builtin = scratch1;
Register shared = scratch0;
__ mov(shared, FieldOperand(target, JSFunction::kSharedFunctionInfoOffset));
__ mov(FieldOperand(shared, SharedFunctionInfo::kCodeOffset),
target_builtin);
__ push(eax); // Write barrier clobbers these below.
__ push(target_builtin);
__ RecordWriteField(shared, SharedFunctionInfo::kCodeOffset, target_builtin,
eax, kDontSaveFPRegs, OMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
__ pop(target_builtin); // eax is popped later, shared is now available.
// And second to the target function.
__ mov(FieldOperand(target, JSFunction::kCodeOffset), target_builtin);
__ push(target_builtin); // Write barrier clobbers these below.
__ RecordWriteField(target, JSFunction::kCodeOffset, target_builtin, eax,
kDontSaveFPRegs, OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
__ pop(target_builtin);
__ pop(eax);
// All copying is done. Jump to the deserialized code object.
__ lea(target_builtin, FieldOperand(target_builtin, Code::kHeaderSize));
__ jmp(target_builtin);
}
__ bind(&deserialize_in_runtime);
GenerateTailCallToReturnedCode(masm, Runtime::kDeserializeLazy);
}
void Builtins::Generate_InstantiateAsmJs(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : argument count (preserved for callee)
......
......@@ -1599,6 +1599,93 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
}
// Lazy deserialization design doc: http://goo.gl/dxkYDZ.
void Builtins::Generate_DeserializeLazy(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : argument count (preserved for callee)
// -- a3 : new target (preserved for callee)
// -- a1 : target function (preserved for callee)
// -----------------------------------
Label deserialize_in_runtime;
Register target = a1; // Must be preserved
Register scratch0 = a2;
Register scratch1 = t0;
CHECK(!scratch0.is(a0) && !scratch0.is(a3) && !scratch0.is(a1));
CHECK(!scratch1.is(a0) && !scratch1.is(a3) && !scratch1.is(a1));
CHECK(!scratch0.is(scratch1));
// Load the builtin id for lazy deserialization from SharedFunctionInfo.
__ AssertFunction(target);
__ lw(scratch0,
FieldMemOperand(target, JSFunction::kSharedFunctionInfoOffset));
__ lw(scratch1,
FieldMemOperand(scratch0, SharedFunctionInfo::kFunctionDataOffset));
__ AssertSmi(scratch1);
// The builtin may already have been deserialized. If that is the case, it is
// stored in the builtins table, and we can copy to correct code object to
// both the shared function info and function without calling into runtime.
//
// Otherwise, we need to call into runtime to deserialize.
{
// Load the code object at builtins_table[builtin_id] into scratch1.
__ SmiUntag(scratch1);
__ li(scratch0,
Operand(ExternalReference::builtins_address(masm->isolate())));
__ Lsa(scratch1, scratch0, scratch1, kPointerSizeLog2);
__ lw(scratch1, MemOperand(scratch1));
// Check if the loaded code object has already been deserialized. This is
// the case iff it does not equal DeserializeLazy.
__ Move(scratch0, masm->CodeObject());
__ Branch(&deserialize_in_runtime, eq, scratch1, Operand(scratch0));
}
{
// If we've reached this spot, the target builtin has been deserialized and
// we simply need to copy it over. First to the shared function info.
Register target_builtin = scratch1;
Register shared = scratch0;
__ lw(shared,
FieldMemOperand(target, JSFunction::kSharedFunctionInfoOffset));
CHECK(!t1.is(target) && !t1.is(scratch0) && !t1.is(scratch1));
CHECK(!t3.is(target) && !t3.is(scratch0) && !t3.is(scratch1));
__ sw(target_builtin,
FieldMemOperand(shared, SharedFunctionInfo::kCodeOffset));
__ mov(t3, target_builtin); // Write barrier clobbers t3 below.
__ RecordWriteField(shared, SharedFunctionInfo::kCodeOffset, t3, t1,
kRAHasNotBeenSaved, kDontSaveFPRegs,
OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
// And second to the target function.
__ sw(target_builtin, FieldMemOperand(target, JSFunction::kCodeOffset));
__ mov(t3, target_builtin); // Write barrier clobbers t3 below.
__ RecordWriteField(target, JSFunction::kCodeOffset, t3, t1,
kRAHasNotBeenSaved, kDontSaveFPRegs,
OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
// All copying is done. Jump to the deserialized code object.
__ Jump(target_builtin, Code::kHeaderSize - kHeapObjectTag);
}
__ bind(&deserialize_in_runtime);
GenerateTailCallToReturnedCode(masm, Runtime::kDeserializeLazy);
}
void Builtins::Generate_InstantiateAsmJs(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : argument count (preserved for callee)
......
......@@ -1603,6 +1603,95 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
}
// Lazy deserialization design doc: http://goo.gl/dxkYDZ.
void Builtins::Generate_DeserializeLazy(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : argument count (preserved for callee)
// -- a3 : new target (preserved for callee)
// -- a1 : target function (preserved for callee)
// -----------------------------------
Label deserialize_in_runtime;
Register target = a1; // Must be preserved
Register scratch0 = a2;
Register scratch1 = t0;
CHECK(!scratch0.is(a0) && !scratch0.is(a3) && !scratch0.is(a1));
CHECK(!scratch1.is(a0) && !scratch1.is(a3) && !scratch1.is(a1));
CHECK(!scratch0.is(scratch1));
// Load the builtin id for lazy deserialization from SharedFunctionInfo.
__ AssertFunction(target);
__ Ld(scratch0,
FieldMemOperand(target, JSFunction::kSharedFunctionInfoOffset));
__ Ld(scratch1,
FieldMemOperand(scratch0, SharedFunctionInfo::kFunctionDataOffset));
__ AssertSmi(scratch1);
// The builtin may already have been deserialized. If that is the case, it is
// stored in the builtins table, and we can copy to correct code object to
// both the shared function info and function without calling into runtime.
//
// Otherwise, we need to call into runtime to deserialize.
{
// Load the code object at builtins_table[builtin_id] into scratch1.
__ SmiUntag(scratch1);
__ li(scratch0,
Operand(ExternalReference::builtins_address(masm->isolate())));
__ Dlsa(scratch1, scratch0, scratch1, kPointerSizeLog2);
__ Ld(scratch1, MemOperand(scratch1));
// Check if the loaded code object has already been deserialized. This is
// the case iff it does not equal DeserializeLazy.
__ Move(scratch0, masm->CodeObject());
__ Branch(&deserialize_in_runtime, eq, scratch1, Operand(scratch0));
}
{
// If we've reached this spot, the target builtin has been deserialized and
// we simply need to copy it over. First to the shared function info.
Register target_builtin = scratch1;
Register shared = scratch0;
__ Ld(shared,
FieldMemOperand(target, JSFunction::kSharedFunctionInfoOffset));
CHECK(!t1.is(target) && !t1.is(scratch0) && !t1.is(scratch1));
CHECK(!t3.is(target) && !t3.is(scratch0) && !t3.is(scratch1));
__ Sd(target_builtin,
FieldMemOperand(shared, SharedFunctionInfo::kCodeOffset));
__ mov(t3, target_builtin); // Write barrier clobbers t3 below.
__ RecordWriteField(shared, SharedFunctionInfo::kCodeOffset, t3, t1,
kRAHasNotBeenSaved, kDontSaveFPRegs,
OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
// And second to the target function.
__ Sd(target_builtin, FieldMemOperand(target, JSFunction::kCodeOffset));
__ mov(t3, target_builtin); // Write barrier clobbers t3 below.
__ RecordWriteField(target, JSFunction::kCodeOffset, t3, t1,
kRAHasNotBeenSaved, kDontSaveFPRegs,
OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
// All copying is done. Jump to the deserialized code object.
__ Daddu(target_builtin, target_builtin,
Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(target_builtin);
}
__ bind(&deserialize_in_runtime);
GenerateTailCallToReturnedCode(masm, Runtime::kDeserializeLazy);
}
void Builtins::Generate_InstantiateAsmJs(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : argument count (preserved for callee)
......
......@@ -1371,6 +1371,91 @@ void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
}
// Lazy deserialization design doc: http://goo.gl/dxkYDZ.
void Builtins::Generate_DeserializeLazy(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : argument count (preserved for callee)
// -- rdx : new target (preserved for callee)
// -- rdi : target function (preserved for callee)
// -----------------------------------
Label deserialize_in_runtime;
Register target = rdi; // Must be preserved
Register scratch0 = rbx;
Register scratch1 = kScratchRegister;
CHECK(!scratch0.is(rax) && !scratch0.is(rdx) && !scratch0.is(rdi));
CHECK(!scratch1.is(rax) && !scratch1.is(rdx) && !scratch1.is(rdi));
CHECK(!scratch0.is(scratch1));
// Load the builtin id for lazy deserialization from SharedFunctionInfo.
__ AssertFunction(target);
__ movp(scratch0,
FieldOperand(target, JSFunction::kSharedFunctionInfoOffset));
__ movp(scratch1,
FieldOperand(scratch0, SharedFunctionInfo::kFunctionDataOffset));
__ AssertSmi(scratch1);
// The builtin may already have been deserialized. If that is the case, it is
// stored in the builtins table, and we can copy to correct code object to
// both the shared function info and function without calling into runtime.
//
// Otherwise, we need to call into runtime to deserialize.
{
// Load the code object at builtins_table[builtin_id] into scratch1.
__ SmiToInteger32(scratch1, scratch1);
__ Move(scratch0, ExternalReference::builtins_address(masm->isolate()));
__ movp(scratch1, Operand(scratch0, scratch1, times_pointer_size, 0));
// Check if the loaded code object has already been deserialized. This is
// the case iff it does not equal DeserializeLazy.
__ Move(scratch0, masm->CodeObject());
__ cmpp(scratch1, scratch0);
__ j(equal, &deserialize_in_runtime);
}
{
// If we've reached this spot, the target builtin has been deserialized and
// we simply need to copy it over. First to the shared function info.
Register target_builtin = scratch1;
Register shared = scratch0;
__ movp(shared,
FieldOperand(target, JSFunction::kSharedFunctionInfoOffset));
CHECK(!r14.is(target) && !r14.is(scratch0) && !r14.is(scratch1));
CHECK(!r15.is(target) && !r15.is(scratch0) && !r15.is(scratch1));
__ movp(FieldOperand(shared, SharedFunctionInfo::kCodeOffset),
target_builtin);
__ movp(r14, target_builtin); // Write barrier clobbers r14 below.
__ RecordWriteField(shared, SharedFunctionInfo::kCodeOffset, r14, r15,
kDontSaveFPRegs, OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
// And second to the target function.
__ movp(FieldOperand(target, JSFunction::kCodeOffset), target_builtin);
__ movp(r14, target_builtin); // Write barrier clobbers r14 below.
__ RecordWriteField(target, JSFunction::kCodeOffset, r14, r15,
kDontSaveFPRegs, OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
// All copying is done. Jump to the deserialized code object.
__ leap(target_builtin, FieldOperand(target_builtin, Code::kHeaderSize));
__ jmp(target_builtin);
}
__ bind(&deserialize_in_runtime);
GenerateTailCallToReturnedCode(masm, Runtime::kDeserializeLazy);
}
void Builtins::Generate_InstantiateAsmJs(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : argument count (preserved for callee)
......
......@@ -537,7 +537,7 @@ RUNTIME_FUNCTION(Runtime_DeserializeLazy) {
shared->set_code(code);
function->set_code(code);
return isolate->heap()->undefined_value();
return code;
}
RUNTIME_FUNCTION(Runtime_IncrementUseCounter) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment