| Index: src/ia32/builtins-ia32.cc
|
| diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
|
| index 8e0376991e54a87b9d9678cfa9eb276262a12177..745b6d123417c8072d836d212ac53710c7996edc 100644
|
| --- a/src/ia32/builtins-ia32.cc
|
| +++ b/src/ia32/builtins-ia32.cc
|
| @@ -866,6 +866,144 @@ void Builtins::Generate_InterpreterEnterExceptionHandler(MacroAssembler* masm) {
|
|
|
|
|
| void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
| + // ----------- S t a t e -------------
|
| + // -- edx : new target (preserved for callee)
|
| + // -- edi : target function (preserved for callee)
|
| + // -----------------------------------
|
| + // First lookup code, maybe we don't need to compile!
|
| + Label gotta_call_runtime, gotta_call_runtime_no_stack;
|
| + Label maybe_call_runtime;
|
| + Label try_shared;
|
| + Label loop_top, loop_bottom;
|
| +
|
| + Register closure = edi;
|
| + Register new_target = edx;
|
| + __ push(new_target);
|
| + __ push(closure);
|
| +
|
| + Register map = eax;
|
| + Register index = ebx;
|
| + __ mov(map, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset));
|
| + __ mov(map, FieldOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
|
| + __ mov(index, FieldOperand(map, FixedArray::kLengthOffset));
|
| + __ cmp(index, Immediate(Smi::FromInt(2)));
|
| + __ j(less, &gotta_call_runtime);
|
| +
|
| + // Find literals.
|
| + // edx : native context
|
| + // ebx : length / index
|
| + // eax : optimized code map
|
| + // stack[0] : new target
|
| + // stack[4] : closure
|
| + Register native_context = edx;
|
| + __ mov(native_context, NativeContextOperand());
|
| +
|
| + __ bind(&loop_top);
|
| + Register temp = edi;
|
| +
|
| + // Does the native context match?
|
| + __ mov(temp, FieldOperand(map, index, times_half_pointer_size,
|
| + SharedFunctionInfo::OffsetToPreviousContext()));
|
| + __ mov(temp, FieldOperand(temp, WeakCell::kValueOffset));
|
| + __ cmp(temp, native_context);
|
| + __ j(not_equal, &loop_bottom);
|
| + // OSR id set to none?
|
| + __ mov(temp, FieldOperand(map, index, times_half_pointer_size,
|
| + SharedFunctionInfo::OffsetToPreviousOsrAstId()));
|
| + const int bailout_id = BailoutId::None().ToInt();
|
| + __ cmp(temp, Immediate(Smi::FromInt(bailout_id)));
|
| + __ j(not_equal, &loop_bottom);
|
| + // Literals available?
|
| + __ mov(temp, FieldOperand(map, index, times_half_pointer_size,
|
| + SharedFunctionInfo::OffsetToPreviousLiterals()));
|
| + __ mov(temp, FieldOperand(temp, WeakCell::kValueOffset));
|
| + __ JumpIfSmi(temp, &gotta_call_runtime);
|
| +
|
| + // Save the literals in the closure.
|
| + __ mov(ecx, Operand(esp, 0));
|
| + __ mov(FieldOperand(ecx, JSFunction::kLiteralsOffset), temp);
|
| + __ push(index);
|
| + __ RecordWriteField(ecx, JSFunction::kLiteralsOffset, temp, index,
|
| + kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
| + __ pop(index);
|
| +
|
| + // Code available?
|
| + Register entry = ecx;
|
| + __ mov(entry, FieldOperand(map, index, times_half_pointer_size,
|
| + SharedFunctionInfo::OffsetToPreviousCachedCode()));
|
| + __ mov(entry, FieldOperand(entry, WeakCell::kValueOffset));
|
| + __ JumpIfSmi(entry, &maybe_call_runtime);
|
| +
|
| + // Found literals and code. Get them into the closure and return.
|
| + __ pop(closure);
|
| + // Store code entry in the closure.
|
| + __ lea(entry, FieldOperand(entry, Code::kHeaderSize));
|
| +
|
| + Label install_optimized_code_and_tailcall;
|
| + __ bind(&install_optimized_code_and_tailcall);
|
| + __ mov(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry);
|
| +
|
| + // Link the closure into the optimized function list.
|
| + // ecx : code entry
|
| + // edx : native context
|
| + // edi : closure
|
| + __ 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);
|
| + __ jmp(entry);
|
| +
|
| + __ bind(&loop_bottom);
|
| + __ sub(index, Immediate(Smi::FromInt(SharedFunctionInfo::kEntryLength)));
|
| + __ cmp(index, Immediate(Smi::FromInt(1)));
|
| + __ j(greater, &loop_top);
|
| +
|
| + // We found neither literals nor code.
|
| + __ jmp(&gotta_call_runtime);
|
| +
|
| + __ bind(&maybe_call_runtime);
|
| + __ pop(closure);
|
| +
|
| + // Last possibility. Check the context free optimized code map entry.
|
| + __ mov(entry, FieldOperand(map, FixedArray::kHeaderSize +
|
| + SharedFunctionInfo::kSharedCodeIndex));
|
| + __ mov(entry, FieldOperand(entry, WeakCell::kValueOffset));
|
| + __ JumpIfSmi(entry, &try_shared);
|
| +
|
| + // Store code entry in the closure.
|
| + __ lea(entry, FieldOperand(entry, Code::kHeaderSize));
|
| + __ jmp(&install_optimized_code_and_tailcall);
|
| +
|
| + __ bind(&try_shared);
|
| + __ pop(new_target);
|
| + // Is the full code valid?
|
| + __ mov(entry, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset));
|
| + __ mov(entry, FieldOperand(entry, SharedFunctionInfo::kCodeOffset));
|
| + __ mov(ebx, FieldOperand(entry, Code::kFlagsOffset));
|
| + __ and_(ebx, Code::KindField::kMask);
|
| + __ shr(ebx, Code::KindField::kShift);
|
| + __ cmp(ebx, Immediate(Code::BUILTIN));
|
| + __ j(equal, &gotta_call_runtime_no_stack);
|
| + // Yes, install the full code.
|
| + __ lea(entry, FieldOperand(entry, Code::kHeaderSize));
|
| + __ mov(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry);
|
| + __ jmp(entry);
|
| +
|
| + __ bind(&gotta_call_runtime);
|
| + __ pop(closure);
|
| + __ pop(new_target);
|
| + __ bind(&gotta_call_runtime_no_stack);
|
| CallRuntimePassFunction(masm, Runtime::kCompileLazy);
|
| GenerateTailCallToReturnedCode(masm);
|
| }
|
|
|