static MacroAssemblerCodeRef linkForGenerator(VM* vm, FunctionPtr lazyLink, FunctionPtr notJSFunction, const char* name) { JSInterfaceJIT jit; JSInterfaceJIT::JumpList slowCase; #if USE(JSVALUE64) slowCase.append(jit.emitJumpIfNotJSCell(JSInterfaceJIT::regT0)); slowCase.append(jit.emitJumpIfNotType(JSInterfaceJIT::regT0, JSInterfaceJIT::regT1, JSFunctionType)); #else // USE(JSVALUE64) slowCase.append(jit.branch32(JSInterfaceJIT::NotEqual, JSInterfaceJIT::regT1, JSInterfaceJIT::TrustedImm32(JSValue::CellTag))); slowCase.append(jit.emitJumpIfNotType(JSInterfaceJIT::regT0, JSInterfaceJIT::regT1, JSFunctionType)); #endif // USE(JSVALUE64) // Finish canonical initialization before JS function call. jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT0, JSFunction::offsetOfScopeChain()), JSInterfaceJIT::regT1); jit.emitPutCellToCallFrameHeader(JSInterfaceJIT::regT1, JSStack::ScopeChain); // Also initialize ReturnPC for use by lazy linking and exceptions. jit.preserveReturnAddressAfterCall(JSInterfaceJIT::regT3); jit.emitPutToCallFrameHeader(JSInterfaceJIT::regT3, JSStack::ReturnPC); jit.storePtr(JSInterfaceJIT::callFrameRegister, &vm->topCallFrame); jit.restoreArgumentReference(); JSInterfaceJIT::Call callLazyLink = jit.call(); jit.restoreReturnAddressBeforeReturn(JSInterfaceJIT::regT3); jit.jump(JSInterfaceJIT::regT0); slowCase.link(&jit); JSInterfaceJIT::Call callNotJSFunction = generateSlowCaseFor(vm, jit); LinkBuffer patchBuffer(*vm, &jit, GLOBAL_THUNK_ID); patchBuffer.link(callLazyLink, lazyLink); patchBuffer.link(callNotJSFunction, notJSFunction); return FINALIZE_CODE(patchBuffer, ("link %s trampoline", name)); }
static MacroAssemblerCodeRef virtualForGenerator(VM* vm, FunctionPtr compile, FunctionPtr notJSFunction, const char* name, CodeSpecializationKind kind) { JSInterfaceJIT jit; JSInterfaceJIT::JumpList slowCase; #if USE(JSVALUE64) slowCase.append(jit.emitJumpIfNotJSCell(JSInterfaceJIT::regT0)); #else // USE(JSVALUE64) slowCase.append(jit.branch32(JSInterfaceJIT::NotEqual, JSInterfaceJIT::regT1, JSInterfaceJIT::TrustedImm32(JSValue::CellTag))); #endif // USE(JSVALUE64) slowCase.append(jit.emitJumpIfNotType(JSInterfaceJIT::regT0, JSInterfaceJIT::regT1, JSFunctionType)); // Finish canonical initialization before JS function call. jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT0, JSFunction::offsetOfScopeChain()), JSInterfaceJIT::regT1); jit.emitPutCellToCallFrameHeader(JSInterfaceJIT::regT1, JSStack::ScopeChain); jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT0, JSFunction::offsetOfExecutable()), JSInterfaceJIT::regT2); JSInterfaceJIT::Jump hasCodeBlock1 = jit.branch32(JSInterfaceJIT::GreaterThanOrEqual, JSInterfaceJIT::Address(JSInterfaceJIT::regT2, FunctionExecutable::offsetOfNumParametersFor(kind)), JSInterfaceJIT::TrustedImm32(0)); jit.preserveReturnAddressAfterCall(JSInterfaceJIT::regT3); jit.storePtr(JSInterfaceJIT::callFrameRegister, &vm->topCallFrame); jit.restoreArgumentReference(); JSInterfaceJIT::Call callCompile = jit.call(); jit.restoreReturnAddressBeforeReturn(JSInterfaceJIT::regT3); jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT0, JSFunction::offsetOfExecutable()), JSInterfaceJIT::regT2); hasCodeBlock1.link(&jit); jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT2, FunctionExecutable::offsetOfJITCodeWithArityCheckFor(kind)), JSInterfaceJIT::regT0); #if !ASSERT_DISABLED JSInterfaceJIT::Jump ok = jit.branchTestPtr(JSInterfaceJIT::NonZero, JSInterfaceJIT::regT0); jit.breakpoint(); ok.link(&jit); #endif jit.jump(JSInterfaceJIT::regT0); slowCase.link(&jit); JSInterfaceJIT::Call callNotJSFunction = generateSlowCaseFor(vm, jit); LinkBuffer patchBuffer(*vm, &jit, GLOBAL_THUNK_ID); patchBuffer.link(callCompile, compile); patchBuffer.link(callNotJSFunction, notJSFunction); return FINALIZE_CODE(patchBuffer, ("virtual %s trampoline", name)); }