MacroAssemblerCodeRef stringLengthTrampolineGenerator(VM* vm) { JSInterfaceJIT jit; #if USE(JSVALUE64) // Check eax is a string JSInterfaceJIT::Jump failureCases1 = jit.emitJumpIfNotJSCell(JSInterfaceJIT::regT0); JSInterfaceJIT::Jump failureCases2 = jit.branchPtr( JSInterfaceJIT::NotEqual, JSInterfaceJIT::Address( JSInterfaceJIT::regT0, JSCell::structureOffset()), JSInterfaceJIT::TrustedImmPtr(vm->stringStructure.get())); // Checks out okay! - get the length from the Ustring. jit.load32( JSInterfaceJIT::Address(JSInterfaceJIT::regT0, JSString::offsetOfLength()), JSInterfaceJIT::regT0); JSInterfaceJIT::Jump failureCases3 = jit.branch32( JSInterfaceJIT::LessThan, JSInterfaceJIT::regT0, JSInterfaceJIT::TrustedImm32(0)); // regT0 contains a 64 bit value (is positive, is zero extended) so we don't need sign extend here. jit.emitFastArithIntToImmNoCheck(JSInterfaceJIT::regT0, JSInterfaceJIT::regT0); #else // USE(JSVALUE64) // regT0 holds payload, regT1 holds tag JSInterfaceJIT::Jump failureCases1 = jit.branch32( JSInterfaceJIT::NotEqual, JSInterfaceJIT::regT1, JSInterfaceJIT::TrustedImm32(JSValue::CellTag)); JSInterfaceJIT::Jump failureCases2 = jit.branchPtr( JSInterfaceJIT::NotEqual, JSInterfaceJIT::Address(JSInterfaceJIT::regT0, JSCell::structureOffset()), JSInterfaceJIT::TrustedImmPtr(vm->stringStructure.get())); // Checks out okay! - get the length from the Ustring. jit.load32( JSInterfaceJIT::Address(JSInterfaceJIT::regT0, JSString::offsetOfLength()), JSInterfaceJIT::regT2); JSInterfaceJIT::Jump failureCases3 = jit.branch32( JSInterfaceJIT::Above, JSInterfaceJIT::regT2, JSInterfaceJIT::TrustedImm32(INT_MAX)); jit.move(JSInterfaceJIT::regT2, JSInterfaceJIT::regT0); jit.move(JSInterfaceJIT::TrustedImm32(JSValue::Int32Tag), JSInterfaceJIT::regT1); #endif // USE(JSVALUE64) jit.ret(); JSInterfaceJIT::Call failureCases1Call = jit.makeTailRecursiveCall(failureCases1); JSInterfaceJIT::Call failureCases2Call = jit.makeTailRecursiveCall(failureCases2); JSInterfaceJIT::Call failureCases3Call = jit.makeTailRecursiveCall(failureCases3); LinkBuffer patchBuffer(*vm, &jit, GLOBAL_THUNK_ID); patchBuffer.link(failureCases1Call, FunctionPtr(cti_op_get_by_id_string_fail)); patchBuffer.link(failureCases2Call, FunctionPtr(cti_op_get_by_id_string_fail)); patchBuffer.link(failureCases3Call, FunctionPtr(cti_op_get_by_id_string_fail)); return FINALIZE_CODE(patchBuffer, ("string length trampoline")); }
MacroAssemblerCodeRef arityFixup(VM* vm) { JSInterfaceJIT jit; // We enter with fixup count in regT0 #if USE(JSVALUE64) # if CPU(X86_64) jit.pop(JSInterfaceJIT::regT4); # endif jit.addPtr(JSInterfaceJIT::TrustedImm32(-8), JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3); jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * 8), JSInterfaceJIT::regT2); jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::regT2); // Move current frame regT0 number of slots JSInterfaceJIT::Label copyLoop(jit.label()); jit.load64(JSInterfaceJIT::regT3, JSInterfaceJIT::regT1); jit.store64(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight)); jit.subPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3); jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(copyLoop, &jit); // Fill in regT0 missing arg slots with undefined jit.move(JSInterfaceJIT::regT0, JSInterfaceJIT::regT2); jit.move(JSInterfaceJIT::TrustedImm64(ValueUndefined), JSInterfaceJIT::regT1); JSInterfaceJIT::Label fillUndefinedLoop(jit.label()); jit.store64(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight)); jit.subPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3); jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(fillUndefinedLoop, &jit); // Adjust call frame register to account for missing args jit.lshift32(JSInterfaceJIT::TrustedImm32(3), JSInterfaceJIT::regT0); jit.addPtr(JSInterfaceJIT::regT0, JSInterfaceJIT::callFrameRegister); # if CPU(X86_64) jit.push(JSInterfaceJIT::regT4); # endif jit.ret(); #else # if CPU(X86) jit.pop(JSInterfaceJIT::regT4); # endif jit.addPtr(JSInterfaceJIT::TrustedImm32(-8), JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3); jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * 8), JSInterfaceJIT::regT2); jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::regT2); // Move current frame regT0 number of slots JSInterfaceJIT::Label copyLoop(jit.label()); jit.load32(JSInterfaceJIT::regT3, JSInterfaceJIT::regT1); jit.store32(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight)); jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, 4), JSInterfaceJIT::regT1); jit.store32(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight, 4)); jit.subPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3); jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(copyLoop, &jit); // Fill in regT0 missing arg slots with undefined jit.move(JSInterfaceJIT::regT0, JSInterfaceJIT::regT2); JSInterfaceJIT::Label fillUndefinedLoop(jit.label()); jit.move(JSInterfaceJIT::TrustedImm32(0), JSInterfaceJIT::regT1); jit.store32(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight)); jit.move(JSInterfaceJIT::TrustedImm32(JSValue::UndefinedTag), JSInterfaceJIT::regT1); jit.store32(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight, 4)); jit.subPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3); jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(fillUndefinedLoop, &jit); // Adjust call frame register to account for missing args jit.lshift32(JSInterfaceJIT::TrustedImm32(3), JSInterfaceJIT::regT0); jit.addPtr(JSInterfaceJIT::regT0, JSInterfaceJIT::callFrameRegister); # if CPU(X86) jit.push(JSInterfaceJIT::regT4); # endif jit.ret(); #endif LinkBuffer patchBuffer(*vm, &jit, GLOBAL_THUNK_ID); return FINALIZE_CODE(patchBuffer, ("fixup arity")); }