https://bugs.webkit.org/show_bug.cgi?id=178647
Reviewed by Saam Barati.
There is much code counting slow cases in fast paths to call `linkSlowCase` carefully. This is really error-prone
since the number of slow cases depends on values of instruction's metadata. We have linkAllSlowCasesForBytecodeOffset,
which drains all slow cases for a specified bytecode offset. In typical cases like just calling a slow path function,
this is enough. We use linkAllSlowCasesForBytecodeOffset as much as possible. It significantly simplifies the code.
* jit/JIT.h:
(JSC::JIT::linkAllSlowCases):
* jit/JITArithmetic.cpp:
(JSC::JIT::emitSlow_op_unsigned):
(JSC::JIT::emit_compareAndJump):
(JSC::JIT::emit_compareAndJumpSlow):
(JSC::JIT::emitSlow_op_inc):
(JSC::JIT::emitSlow_op_dec):
(JSC::JIT::emitSlow_op_mod):
(JSC::JIT::emitSlow_op_negate):
(JSC::JIT::emitSlow_op_bitand):
(JSC::JIT::emitSlow_op_bitor):
(JSC::JIT::emitSlow_op_bitxor):
(JSC::JIT::emitSlow_op_lshift):
(JSC::JIT::emitSlow_op_rshift):
(JSC::JIT::emitSlow_op_urshift):
(JSC::JIT::emitSlow_op_add):
(JSC::JIT::emitSlow_op_div):
(JSC::JIT::emitSlow_op_mul):
(JSC::JIT::emitSlow_op_sub):
* jit/JITArithmetic32_64.cpp:
(JSC::JIT::emit_compareAndJumpSlow):
(JSC::JIT::emitSlow_op_unsigned):
(JSC::JIT::emitSlow_op_inc):
(JSC::JIT::emitSlow_op_dec):
(JSC::JIT::emitSlow_op_mod):
* jit/JITCall.cpp:
(JSC::JIT::compileCallEvalSlowCase):
(JSC::JIT::compileOpCallSlowCase):
* jit/JITCall32_64.cpp:
(JSC::JIT::compileCallEvalSlowCase):
(JSC::JIT::compileOpCallSlowCase):
* jit/JITInlines.h:
(JSC::JIT::linkAllSlowCasesForBytecodeOffset):
* jit/JITOpcodes.cpp:
(JSC::JIT::emitSlow_op_new_object):
(JSC::JIT::emitSlow_op_create_this):
(JSC::JIT::emitSlow_op_check_tdz):
(JSC::JIT::emitSlow_op_to_this):
(JSC::JIT::emitSlow_op_to_primitive):
(JSC::JIT::emitSlow_op_not):
(JSC::JIT::emitSlow_op_eq):
(JSC::JIT::emitSlow_op_neq):
(JSC::JIT::emitSlow_op_stricteq):
(JSC::JIT::emitSlow_op_nstricteq):
(JSC::JIT::emitSlow_op_instanceof):
(JSC::JIT::emitSlow_op_instanceof_custom):
(JSC::JIT::emitSlow_op_to_number):
(JSC::JIT::emitSlow_op_to_string):
(JSC::JIT::emitSlow_op_loop_hint):
(JSC::JIT::emitSlow_op_check_traps):
(JSC::JIT::emitSlow_op_has_indexed_property):
(JSC::JIT::emitSlow_op_get_direct_pname):
(JSC::JIT::emitSlow_op_has_structure_property):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emitSlow_op_new_object):
(JSC::JIT::emitSlow_op_instanceof):
(JSC::JIT::emitSlow_op_instanceof_custom):
(JSC::JIT::emitSlow_op_to_primitive):
(JSC::JIT::emitSlow_op_not):
(JSC::JIT::emitSlow_op_stricteq):
(JSC::JIT::emitSlow_op_nstricteq):
(JSC::JIT::emitSlow_op_to_number):
(JSC::JIT::emitSlow_op_to_string):
(JSC::JIT::emitSlow_op_create_this):
(JSC::JIT::emitSlow_op_to_this):
(JSC::JIT::emitSlow_op_check_tdz):
(JSC::JIT::emitSlow_op_has_indexed_property):
(JSC::JIT::emitSlow_op_get_direct_pname):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emitSlow_op_try_get_by_id):
(JSC::JIT::emitSlow_op_get_by_id):
(JSC::JIT::emitSlow_op_get_by_id_with_this):
(JSC::JIT::emitSlow_op_put_by_id):
(JSC::JIT::emitSlow_op_resolve_scope):
(JSC::JIT::emitSlow_op_get_from_scope):
(JSC::JIT::emitSlow_op_put_to_scope):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emitSlow_op_try_get_by_id):
(JSC::JIT::emitSlow_op_get_by_id):
(JSC::JIT::emitSlow_op_get_by_id_with_this):
(JSC::JIT::emitSlow_op_put_by_id):
(JSC::JIT::emitSlow_op_resolve_scope):
(JSC::JIT::emitSlow_op_get_from_scope):
(JSC::JIT::emitSlow_op_put_to_scope):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@223824
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
2017-10-22 Yusuke Suzuki <utatane.tea@gmail.com>
+ [JSC][Baseline] Use linkAllSlowCasesForBytecodeOffset as much as possible to simplify slow cases handling
+ https://bugs.webkit.org/show_bug.cgi?id=178647
+
+ Reviewed by Saam Barati.
+
+ There is much code counting slow cases in fast paths to call `linkSlowCase` carefully. This is really error-prone
+ since the number of slow cases depends on values of instruction's metadata. We have linkAllSlowCasesForBytecodeOffset,
+ which drains all slow cases for a specified bytecode offset. In typical cases like just calling a slow path function,
+ this is enough. We use linkAllSlowCasesForBytecodeOffset as much as possible. It significantly simplifies the code.
+
+ * jit/JIT.h:
+ (JSC::JIT::linkAllSlowCases):
+ * jit/JITArithmetic.cpp:
+ (JSC::JIT::emitSlow_op_unsigned):
+ (JSC::JIT::emit_compareAndJump):
+ (JSC::JIT::emit_compareAndJumpSlow):
+ (JSC::JIT::emitSlow_op_inc):
+ (JSC::JIT::emitSlow_op_dec):
+ (JSC::JIT::emitSlow_op_mod):
+ (JSC::JIT::emitSlow_op_negate):
+ (JSC::JIT::emitSlow_op_bitand):
+ (JSC::JIT::emitSlow_op_bitor):
+ (JSC::JIT::emitSlow_op_bitxor):
+ (JSC::JIT::emitSlow_op_lshift):
+ (JSC::JIT::emitSlow_op_rshift):
+ (JSC::JIT::emitSlow_op_urshift):
+ (JSC::JIT::emitSlow_op_add):
+ (JSC::JIT::emitSlow_op_div):
+ (JSC::JIT::emitSlow_op_mul):
+ (JSC::JIT::emitSlow_op_sub):
+ * jit/JITArithmetic32_64.cpp:
+ (JSC::JIT::emit_compareAndJumpSlow):
+ (JSC::JIT::emitSlow_op_unsigned):
+ (JSC::JIT::emitSlow_op_inc):
+ (JSC::JIT::emitSlow_op_dec):
+ (JSC::JIT::emitSlow_op_mod):
+ * jit/JITCall.cpp:
+ (JSC::JIT::compileCallEvalSlowCase):
+ (JSC::JIT::compileOpCallSlowCase):
+ * jit/JITCall32_64.cpp:
+ (JSC::JIT::compileCallEvalSlowCase):
+ (JSC::JIT::compileOpCallSlowCase):
+ * jit/JITInlines.h:
+ (JSC::JIT::linkAllSlowCasesForBytecodeOffset):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emitSlow_op_new_object):
+ (JSC::JIT::emitSlow_op_create_this):
+ (JSC::JIT::emitSlow_op_check_tdz):
+ (JSC::JIT::emitSlow_op_to_this):
+ (JSC::JIT::emitSlow_op_to_primitive):
+ (JSC::JIT::emitSlow_op_not):
+ (JSC::JIT::emitSlow_op_eq):
+ (JSC::JIT::emitSlow_op_neq):
+ (JSC::JIT::emitSlow_op_stricteq):
+ (JSC::JIT::emitSlow_op_nstricteq):
+ (JSC::JIT::emitSlow_op_instanceof):
+ (JSC::JIT::emitSlow_op_instanceof_custom):
+ (JSC::JIT::emitSlow_op_to_number):
+ (JSC::JIT::emitSlow_op_to_string):
+ (JSC::JIT::emitSlow_op_loop_hint):
+ (JSC::JIT::emitSlow_op_check_traps):
+ (JSC::JIT::emitSlow_op_has_indexed_property):
+ (JSC::JIT::emitSlow_op_get_direct_pname):
+ (JSC::JIT::emitSlow_op_has_structure_property):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emitSlow_op_new_object):
+ (JSC::JIT::emitSlow_op_instanceof):
+ (JSC::JIT::emitSlow_op_instanceof_custom):
+ (JSC::JIT::emitSlow_op_to_primitive):
+ (JSC::JIT::emitSlow_op_not):
+ (JSC::JIT::emitSlow_op_stricteq):
+ (JSC::JIT::emitSlow_op_nstricteq):
+ (JSC::JIT::emitSlow_op_to_number):
+ (JSC::JIT::emitSlow_op_to_string):
+ (JSC::JIT::emitSlow_op_create_this):
+ (JSC::JIT::emitSlow_op_to_this):
+ (JSC::JIT::emitSlow_op_check_tdz):
+ (JSC::JIT::emitSlow_op_has_indexed_property):
+ (JSC::JIT::emitSlow_op_get_direct_pname):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emitSlow_op_try_get_by_id):
+ (JSC::JIT::emitSlow_op_get_by_id):
+ (JSC::JIT::emitSlow_op_get_by_id_with_this):
+ (JSC::JIT::emitSlow_op_put_by_id):
+ (JSC::JIT::emitSlow_op_resolve_scope):
+ (JSC::JIT::emitSlow_op_get_from_scope):
+ (JSC::JIT::emitSlow_op_put_to_scope):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emitSlow_op_try_get_by_id):
+ (JSC::JIT::emitSlow_op_get_by_id):
+ (JSC::JIT::emitSlow_op_get_by_id_with_this):
+ (JSC::JIT::emitSlow_op_put_by_id):
+ (JSC::JIT::emitSlow_op_resolve_scope):
+ (JSC::JIT::emitSlow_op_get_from_scope):
+ (JSC::JIT::emitSlow_op_put_to_scope):
+
+2017-10-22 Yusuke Suzuki <utatane.tea@gmail.com>
+
[JSC] Clean up baseline slow path
https://bugs.webkit.org/show_bug.cgi?id=178646
void linkAllSlowCasesForBytecodeOffset(Vector<SlowCaseEntry>& slowCases,
Vector<SlowCaseEntry>::iterator&, unsigned bytecodeOffset);
+ void linkAllSlowCases(Vector<SlowCaseEntry>::iterator& iter)
+ {
+ linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
+ }
+
MacroAssembler::Call appendCallWithExceptionCheck(const FunctionPtr&);
#if OS(WINDOWS) && CPU(X86_64)
MacroAssembler::Call appendCallWithExceptionCheckAndSlowPathReturnType(const FunctionPtr&);
void JIT::emitSlow_op_unsigned(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_unsigned);
slowPathCall.call();
emitJumpSlowCaseIfNotInt(regT0);
int32_t op2imm = getOperandConstantInt(op2);
addJump(branch32(condition, regT0, Imm32(op2imm)), target);
- } else if (isOperandConstantInt(op1)) {
+ return;
+ }
+ if (isOperandConstantInt(op1)) {
emitGetVirtualRegister(op2, regT1);
emitJumpSlowCaseIfNotInt(regT1);
int32_t op1imm = getOperandConstantInt(op1);
addJump(branch32(commute(condition), regT1, Imm32(op1imm)), target);
- } else {
- emitGetVirtualRegisters(op1, regT0, op2, regT1);
- emitJumpSlowCaseIfNotInt(regT0);
- emitJumpSlowCaseIfNotInt(regT1);
-
- addJump(branch32(condition, regT0, regT1), target);
+ return;
}
+
+ emitGetVirtualRegisters(op1, regT0, op2, regT1);
+ emitJumpSlowCaseIfNotInt(regT0);
+ emitJumpSlowCaseIfNotInt(regT1);
+
+ addJump(branch32(condition, regT0, regT1), target);
}
void JIT::emit_compareUnsignedAndJump(int op1, int op2, unsigned target, RelationalCondition condition)
// - constant int immediate to floating-point number
// - floating-point number to floating-point number.
if (isOperandConstantChar(op1) || isOperandConstantChar(op2)) {
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
emitGetVirtualRegister(op1, argumentGPR0);
emitGetVirtualRegister(op2, argumentGPR1);
}
if (isOperandConstantInt(op2)) {
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
if (supportsFloatingPoint()) {
Jump fail1 = emitJumpIfNotNumber(regT0);
emitGetVirtualRegister(op2, regT1);
callOperation(operation, regT0, regT1);
emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, returnValueGPR), target);
- } else if (isOperandConstantInt(op1)) {
- linkSlowCase(iter);
+ return;
+ }
+
+ if (isOperandConstantInt(op1)) {
+ linkAllSlowCases(iter);
if (supportsFloatingPoint()) {
Jump fail1 = emitJumpIfNotNumber(regT1);
emitGetVirtualRegister(op1, regT2);
callOperation(operation, regT2, regT1);
emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, returnValueGPR), target);
- } else {
- linkSlowCase(iter);
+ return;
+ }
- if (supportsFloatingPoint()) {
- Jump fail1 = emitJumpIfNotNumber(regT0);
- Jump fail2 = emitJumpIfNotNumber(regT1);
- Jump fail3 = emitJumpIfInt(regT1);
- add64(tagTypeNumberRegister, regT0);
- add64(tagTypeNumberRegister, regT1);
- move64ToDouble(regT0, fpRegT0);
- move64ToDouble(regT1, fpRegT1);
+ linkSlowCase(iter); // LHS is not Int.
- emitJumpSlowToHot(branchDouble(condition, fpRegT0, fpRegT1), target);
+ if (supportsFloatingPoint()) {
+ Jump fail1 = emitJumpIfNotNumber(regT0);
+ Jump fail2 = emitJumpIfNotNumber(regT1);
+ Jump fail3 = emitJumpIfInt(regT1);
+ add64(tagTypeNumberRegister, regT0);
+ add64(tagTypeNumberRegister, regT1);
+ move64ToDouble(regT0, fpRegT0);
+ move64ToDouble(regT1, fpRegT1);
- emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jless));
+ emitJumpSlowToHot(branchDouble(condition, fpRegT0, fpRegT1), target);
- fail1.link(this);
- fail2.link(this);
- fail3.link(this);
- }
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jless));
- linkSlowCase(iter);
- callOperation(operation, regT0, regT1);
- emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, returnValueGPR), target);
+ fail1.link(this);
+ fail2.link(this);
+ fail3.link(this);
}
+
+ linkSlowCase(iter); // RHS is not Int.
+ callOperation(operation, regT0, regT1);
+ emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, returnValueGPR), target);
}
void JIT::emit_op_inc(Instruction* currentInstruction)
void JIT::emitSlow_op_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_inc);
slowPathCall.call();
}
void JIT::emitSlow_op_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_dec);
slowPathCall.call();
}
void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mod);
slowPathCall.call();
}
void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
+ linkAllSlowCases(iter);
JITNegIC* negIC = bitwise_cast<JITNegIC*>(m_instructionToMathIC.get(currentInstruction));
emitMathICSlow(negIC, currentInstruction, operationArithNegateProfiledOptimize, operationArithNegateProfiled, operationArithNegateOptimize);
void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_bitand);
slowPathCall.call();
void JIT::emitSlow_op_bitor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_bitor);
slowPathCall.call();
void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_bitxor);
slowPathCall.call();
void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_lshift);
slowPathCall.call();
void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_rshift);
slowPathCall.call();
void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_urshift);
slowPathCall.call();
void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
+ linkAllSlowCases(iter);
JITAddIC* addIC = bitwise_cast<JITAddIC*>(m_instructionToMathIC.get(currentInstruction));
emitMathICSlow(addIC, currentInstruction, operationValueAddProfiledOptimize, operationValueAddProfiled, operationValueAddOptimize);
void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div);
slowPathCall.call();
void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
+ linkAllSlowCases(iter);
JITMulIC* mulIC = bitwise_cast<JITMulIC*>(m_instructionToMathIC.get(currentInstruction));
emitMathICSlow(mulIC, currentInstruction, operationValueMulProfiledOptimize, operationValueMulProfiled, operationValueMulOptimize);
void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
+ linkAllSlowCases(iter);
+
JITSubIC* subIC = bitwise_cast<JITSubIC*>(m_instructionToMathIC.get(currentInstruction));
emitMathICSlow(subIC, currentInstruction, operationValueSubProfiledOptimize, operationValueSubProfiled, operationValueSubOptimize);
}
void JIT::emit_compareAndJumpSlow(int op1, int op2, unsigned target, DoubleCondition, size_t (JIT_OPERATION *operation)(ExecState*, EncodedJSValue, EncodedJSValue), bool invert, Vector<SlowCaseEntry>::iterator& iter)
{
- if (isOperandConstantChar(op1) || isOperandConstantChar(op2)) {
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
- } else {
- if (!supportsFloatingPoint()) {
- if (!isOperandConstantInt(op1) && !isOperandConstantInt(op2))
- linkSlowCase(iter); // int32 check
- linkSlowCase(iter); // int32 check
- } else {
- if (!isOperandConstantInt(op1)) {
- linkSlowCase(iter); // double check
- linkSlowCase(iter); // int32 check
- }
- if (isOperandConstantInt(op1) || !isOperandConstantInt(op2))
- linkSlowCase(iter); // double check
- }
- }
+ linkAllSlowCases(iter);
+
emitLoad(op1, regT1, regT0);
emitLoad(op2, regT3, regT2);
callOperation(operation, regT1, regT0, regT3, regT2);
void JIT::emitSlow_op_unsigned(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_unsigned);
slowPathCall.call();
void JIT::emitSlow_op_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter); // int32 check
- linkSlowCase(iter); // overflow check
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_inc);
slowPathCall.call();
void JIT::emitSlow_op_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter); // int32 check
- linkSlowCase(iter); // overflow check
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_dec);
slowPathCall.call();
void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
#if CPU(X86)
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mod);
slowPathCall.call();
#else
void JIT::compileCallEvalSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
CallLinkInfo* info = m_codeBlock->addCallLinkInfo();
info->setUpCall(CallLinkInfo::Call, CodeOrigin(m_bytecodeOffset), regT0);
- linkSlowCase(iter);
int registerOffset = -instruction[4].u.operand;
addPtr(TrustedImm32(registerOffset * sizeof(Register) + sizeof(CallerFrameAndPC)), callFrameRegister, stackPointerRegister);
return;
}
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs || opcodeID == op_tail_call_forward_arguments)
emitRestoreCalleeSaves();
void JIT::compileCallEvalSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
CallLinkInfo* info = m_codeBlock->addCallLinkInfo();
info->setUpCall(CallLinkInfo::Call, CodeOrigin(m_bytecodeOffset), regT0);
- linkSlowCase(iter);
-
int registerOffset = -instruction[4].u.operand;
int callee = instruction[2].u.operand;
return;
}
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
ALWAYS_INLINE void JIT::linkAllSlowCasesForBytecodeOffset(Vector<SlowCaseEntry>& slowCases, Vector<SlowCaseEntry>::iterator& iter, unsigned bytecodeOffset)
{
- while (iter != slowCases.end() && iter->to == bytecodeOffset) {
- iter->from.link(this);
- ++iter;
- }
+ while (iter != slowCases.end() && iter->to == bytecodeOffset)
+ linkSlowCase(iter);
}
ALWAYS_INLINE void JIT::addSlowCase(Jump jump)
void JIT::emitSlow_op_new_object(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
int dst = currentInstruction[1].u.operand;
Structure* structure = currentInstruction[3].u.objectAllocationProfile->structure();
callOperation(operationNewObject, structure);
void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter); // Callee::m_type != JSFunctionType.
- linkSlowCase(iter); // doesn't have rare data
- linkSlowCase(iter); // doesn't have an allocation profile
- linkSlowCase(iter); // allocation failed (no allocator)
- linkSlowCase(iter); // allocation failed (allocator empty)
- linkSlowCase(iter); // cached function didn't match
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_create_this);
slowPathCall.call();
void JIT::emitSlow_op_check_tdz(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_throw_tdz_error);
slowPathCall.call();
}
void JIT::emitSlow_op_to_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_this);
slowPathCall.call();
void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_primitive);
slowPathCall.call();
void JIT::emitSlow_op_not(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_not);
slowPathCall.call();
void JIT::emitSlow_op_eq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
callOperation(operationCompareEq, regT0, regT1);
emitTagBool(returnValueGPR);
emitPutVirtualRegister(currentInstruction[1].u.operand, returnValueGPR);
void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
callOperation(operationCompareEq, regT0, regT1);
xor32(TrustedImm32(0x1), regT0);
emitTagBool(returnValueGPR);
void JIT::emitSlow_op_stricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_stricteq);
slowPathCall.call();
}
void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_nstricteq);
slowPathCall.call();
}
void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
auto& bytecode = *reinterpret_cast<OpInstanceof*>(currentInstruction);
int dst = bytecode.dst();
int value = bytecode.value();
int proto = bytecode.prototype();
- linkSlowCaseIfNotJSCell(iter, value);
- linkSlowCaseIfNotJSCell(iter, proto);
- linkSlowCase(iter);
- linkSlowCase(iter);
emitGetVirtualRegister(value, regT0);
emitGetVirtualRegister(proto, regT1);
callOperation(operationInstanceOf, dst, regT0, regT1);
void JIT::emitSlow_op_instanceof_custom(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
auto& bytecode = *reinterpret_cast<OpInstanceofCustom*>(currentInstruction);
int dst = bytecode.dst();
int value = bytecode.value();
int constructor = bytecode.constructor();
int hasInstanceValue = bytecode.hasInstanceValue();
- linkSlowCase(iter);
emitGetVirtualRegister(value, regT0);
emitGetVirtualRegister(constructor, regT1);
emitGetVirtualRegister(hasInstanceValue, regT2);
void JIT::emitSlow_op_to_number(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_number);
slowPathCall.call();
void JIT::emitSlow_op_to_string(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter); // Not JSCell.
- linkSlowCase(iter); // Not JSString.
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_string);
slowPathCall.call();
#if ENABLE(DFG_JIT)
// Emit the slow path for the JIT optimization check:
if (canBeOptimized()) {
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
copyCalleeSavesFromFrameOrRegisterToEntryFrameCalleeSavesBuffer(vm()->topEntryFrame);
void JIT::emitSlow_op_check_traps(Instruction*, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
callOperation(operationHandleTraps);
}
void JIT::emitSlow_op_has_indexed_property(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
int dst = currentInstruction[1].u.operand;
int base = currentInstruction[2].u.operand;
int property = currentInstruction[3].u.operand;
ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
-
- linkSlowCaseIfNotJSCell(iter, base); // base cell check
- linkSlowCase(iter); // base array check
- linkSlowCase(iter); // vector length check
- linkSlowCase(iter); // empty value
-
+
Label slowPath = label();
emitGetVirtualRegister(base, regT0);
void JIT::emitSlow_op_get_direct_pname(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- int base = currentInstruction[2].u.operand;
- linkSlowCaseIfNotJSCell(iter, base);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_direct_pname);
slowPathCall.call();
void JIT::emitSlow_op_has_structure_property(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_has_structure_property);
slowPathCall.call();
void JIT::emitSlow_op_new_object(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
int dst = currentInstruction[1].u.operand;
Structure* structure = currentInstruction[3].u.objectAllocationProfile->structure();
callOperation(operationNewObject, structure);
void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
auto& bytecode = *reinterpret_cast<OpInstanceof*>(currentInstruction);
int dst = bytecode.dst();
int value = bytecode.value();
int proto = bytecode.prototype();
- linkSlowCaseIfNotJSCell(iter, value);
- linkSlowCaseIfNotJSCell(iter, proto);
- linkSlowCase(iter);
- linkSlowCase(iter);
-
emitLoad(value, regT1, regT0);
emitLoad(proto, regT3, regT2);
callOperation(operationInstanceOf, dst, regT1, regT0, regT3, regT2);
void JIT::emitSlow_op_instanceof_custom(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
auto& bytecode = *reinterpret_cast<OpInstanceofCustom*>(currentInstruction);
int dst = bytecode.dst();
int value = bytecode.value();
int constructor = bytecode.constructor();
int hasInstanceValue = bytecode.hasInstanceValue();
- linkSlowCase(iter);
-
emitLoad(value, regT1, regT0);
emitLoadPayload(constructor, regT2);
emitLoad(hasInstanceValue, regT4, regT3);
void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_primitive);
slowPathCall.call();
void JIT::emitSlow_op_not(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_not);
slowPathCall.call();
void JIT::emitSlow_op_stricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_stricteq);
slowPathCall.call();
void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_nstricteq);
slowPathCall.call();
void JIT::emitSlow_op_to_number(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_number);
slowPathCall.call();
void JIT::emitSlow_op_to_string(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter); // Not JSCell.
- linkSlowCase(iter); // Not JSString.
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_string);
slowPathCall.call();
void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter); // Callee::m_type != JSFunctionType.
- linkSlowCase(iter); // doesn't have rare data
- linkSlowCase(iter); // doesn't have an allocation profile
- linkSlowCase(iter); // allocation failed (no allocator)
- linkSlowCase(iter); // allocation failed (allocator empty)
- linkSlowCase(iter); // cached function didn't match
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_create_this);
slowPathCall.call();
void JIT::emitSlow_op_to_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_this);
slowPathCall.call();
}
void JIT::emitSlow_op_check_tdz(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_throw_tdz_error);
slowPathCall.call();
}
void JIT::emitSlow_op_has_indexed_property(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
int dst = currentInstruction[1].u.operand;
int base = currentInstruction[2].u.operand;
int property = currentInstruction[3].u.operand;
ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
-
- linkSlowCaseIfNotJSCell(iter, base); // base cell check
- linkSlowCase(iter); // base array check
- linkSlowCase(iter); // vector length check
- linkSlowCase(iter); // empty value
Label slowPath = label();
void JIT::emitSlow_op_get_direct_pname(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- int base = currentInstruction[2].u.operand;
- linkSlowCaseIfNotJSCell(iter, base);
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_direct_pname);
slowPathCall.call();
void JIT::emitSlow_op_try_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
int resultVReg = currentInstruction[1].u.operand;
- int baseVReg = currentInstruction[2].u.operand;
const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
- linkSlowCaseIfNotJSCell(iter, baseVReg);
- linkSlowCase(iter);
-
JITGetByIdGenerator& gen = m_getByIds[m_getByIdIndex++];
Label coldPathBegin = label();
void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
int resultVReg = currentInstruction[1].u.operand;
- int baseVReg = currentInstruction[2].u.operand;
const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
- linkSlowCaseIfNotJSCell(iter, baseVReg);
- linkSlowCase(iter);
-
JITGetByIdGenerator& gen = m_getByIds[m_getByIdIndex++];
Label coldPathBegin = label();
void JIT::emitSlow_op_get_by_id_with_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
int resultVReg = currentInstruction[1].u.operand;
- int baseVReg = currentInstruction[2].u.operand;
- int thisVReg = currentInstruction[3].u.operand;
const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[4].u.operand));
- linkSlowCaseIfNotJSCell(iter, baseVReg);
- linkSlowCaseIfNotJSCell(iter, thisVReg);
- linkSlowCase(iter);
-
JITGetByIdWithThisGenerator& gen = m_getByIdsWithThis[m_getByIdWithThisIndex++];
Label coldPathBegin = label();
void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- int baseVReg = currentInstruction[1].u.operand;
- const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
+ linkAllSlowCases(iter);
- linkSlowCaseIfNotJSCell(iter, baseVReg);
- linkSlowCase(iter);
+ const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
Label coldPathBegin(this);
void JIT::emitSlow_op_resolve_scope(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- ResolveType resolveType = static_cast<ResolveType>(copiedInstruction(currentInstruction)[4].u.operand);
- if (resolveType == GlobalProperty || resolveType == GlobalVar || resolveType == ClosureVar || resolveType == GlobalLexicalVar || resolveType == ModuleVar)
- return;
+ linkAllSlowCases(iter);
- if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
- linkSlowCase(iter); // var injections check for GlobalPropertyWithVarInjectionChecks.
- linkSlowCase(iter); // var injections check for GlobalLexicalVarWithVarInjectionChecks.
- }
-
- linkSlowCase(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_resolve_scope);
slowPathCall.call();
}
void JIT::emitSlow_op_get_from_scope(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- int dst = currentInstruction[1].u.operand;
- ResolveType resolveType = GetPutInfo(copiedInstruction(currentInstruction)[4].u.operand).resolveType();
-
- if (resolveType == GlobalVar || resolveType == ClosureVar)
- return;
-
- if (resolveType == GlobalProperty || resolveType == GlobalPropertyWithVarInjectionChecks)
- linkSlowCase(iter); // bad structure
-
- if (resolveType == GlobalLexicalVarWithVarInjectionChecks) // Var injections check.
- linkSlowCase(iter);
-
- if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
- // GlobalProperty/GlobalPropertyWithVarInjectionChecks
- linkSlowCase(iter); // emitLoadWithStructureCheck
- linkSlowCase(iter); // emitLoadWithStructureCheck
- // GlobalLexicalVar
- linkSlowCase(iter); // TDZ check.
- // GlobalLexicalVarWithVarInjectionChecks.
- linkSlowCase(iter); // var injection check.
- linkSlowCase(iter); // TDZ check.
- }
-
- linkSlowCase(iter);
+ linkAllSlowCases(iter);
+ int dst = currentInstruction[1].u.operand;
callOperation(WithProfile, operationGetFromScope, dst, currentInstruction);
}
void JIT::emitSlow_op_put_to_scope(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
GetPutInfo getPutInfo = GetPutInfo(copiedInstruction(currentInstruction)[4].u.operand);
ResolveType resolveType = getPutInfo.resolveType();
- unsigned linkCount = 0;
- if (resolveType != GlobalVar && resolveType != ClosureVar && resolveType != LocalClosureVar && resolveType != GlobalLexicalVar)
- linkCount++;
- if (resolveType == GlobalVar || resolveType == GlobalVarWithVarInjectionChecks
- || resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks
- || resolveType == ClosureVar || resolveType == ClosureVarWithVarInjectionChecks
- || resolveType == LocalClosureVar)
- linkCount++;
- if (resolveType == GlobalProperty || resolveType == GlobalPropertyWithVarInjectionChecks)
- linkCount++; // bad structure
- if (!isInitialization(getPutInfo.initializationMode()) && (resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks)) // TDZ check.
- linkCount++;
- if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
- // GlobalProperty/GlobalPropertyWithVarInjectionsCheck
- linkCount++; // emitLoadWithStructureCheck
- linkCount++; // emitLoadWithStructureCheck
-
- // GlobalLexicalVar
- bool needsTDZCheck = !isInitialization(getPutInfo.initializationMode());
- if (needsTDZCheck)
- linkCount++;
- linkCount++; // Notify write check.
-
- // GlobalLexicalVarWithVarInjectionsCheck
- linkCount++; // var injection check.
- if (needsTDZCheck)
- linkCount++;
- linkCount++; // Notify write check.
- }
- if (!linkCount)
- return;
- while (linkCount--)
- linkSlowCase(iter);
-
if (resolveType == ModuleVar) {
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_throw_strict_mode_readonly_property_write_error);
slowPathCall.call();
void JIT::emitSlow_op_try_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
int resultVReg = currentInstruction[1].u.operand;
- int baseVReg = currentInstruction[2].u.operand;
const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
- linkSlowCaseIfNotJSCell(iter, baseVReg);
- linkSlowCase(iter);
-
JITGetByIdGenerator& gen = m_getByIds[m_getByIdIndex++];
Label coldPathBegin = label();
void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
int resultVReg = currentInstruction[1].u.operand;
- int baseVReg = currentInstruction[2].u.operand;
const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
- linkSlowCaseIfNotJSCell(iter, baseVReg);
- linkSlowCase(iter);
-
JITGetByIdGenerator& gen = m_getByIds[m_getByIdIndex++];
Label coldPathBegin = label();
void JIT::emitSlow_op_get_by_id_with_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
int resultVReg = currentInstruction[1].u.operand;
- int baseVReg = currentInstruction[2].u.operand;
- int thisVReg = currentInstruction[3].u.operand;
const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[4].u.operand));
- linkSlowCaseIfNotJSCell(iter, baseVReg);
- linkSlowCaseIfNotJSCell(iter, thisVReg);
- linkSlowCase(iter);
-
JITGetByIdWithThisGenerator& gen = m_getByIdsWithThis[m_getByIdWithThisIndex++];
Label coldPathBegin = label();
void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
int base = currentInstruction[1].u.operand;
const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
- linkSlowCaseIfNotJSCell(iter, base);
- linkSlowCase(iter);
-
Label coldPathBegin(this);
// JITPutByIdGenerator only preserve the value and the base's payload, we have to reload the tag.
void JIT::emitSlow_op_resolve_scope(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- ResolveType resolveType = static_cast<ResolveType>(currentInstruction[4].u.operand);
-
- if (resolveType == GlobalProperty || resolveType == GlobalVar || resolveType == ClosureVar || resolveType == GlobalLexicalVar || resolveType == ModuleVar)
- return;
- if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
- linkSlowCase(iter); // Var injections check for GlobalPropertyWithVarInjectionChecks.
- linkSlowCase(iter); // Var injections check for GlobalLexicalVarWithVarInjectionChecks.
- }
+ linkAllSlowCases(iter);
- linkSlowCase(iter);
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_resolve_scope);
slowPathCall.call();
}
void JIT::emitSlow_op_get_from_scope(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- int dst = currentInstruction[1].u.operand;
- ResolveType resolveType = GetPutInfo(currentInstruction[4].u.operand).resolveType();
-
- if (resolveType == GlobalVar || resolveType == ClosureVar)
- return;
-
- if (resolveType == GlobalLexicalVarWithVarInjectionChecks) // Var Injections check.
- linkSlowCase(iter);
-
- if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
- // GlobalProperty/GlobalPropertyWithVarInjectionChecks
- linkSlowCase(iter); // emitLoadWithStructureCheck
- // GlobalLexicalVar
- linkSlowCase(iter); // TDZ check.
- // GlobalLexicalVarWithVarInjectionChecks.
- linkSlowCase(iter); // var injection check.
- linkSlowCase(iter); // TDZ check.
- }
+ linkAllSlowCases(iter);
- linkSlowCase(iter);
+ int dst = currentInstruction[1].u.operand;
callOperation(WithProfile, operationGetFromScope, dst, currentInstruction);
}
void JIT::emitSlow_op_put_to_scope(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ linkAllSlowCases(iter);
+
GetPutInfo getPutInfo = GetPutInfo(currentInstruction[4].u.operand);
ResolveType resolveType = getPutInfo.resolveType();
- unsigned linkCount = 0;
- if (resolveType != GlobalVar && resolveType != ClosureVar && resolveType != LocalClosureVar && resolveType != GlobalLexicalVar)
- linkCount++;
- if (resolveType == GlobalVar || resolveType == GlobalVarWithVarInjectionChecks
- || resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks
- || resolveType == ClosureVar || resolveType == ClosureVarWithVarInjectionChecks
- || resolveType == LocalClosureVar)
- linkCount++;
- if (!isInitialization(getPutInfo.initializationMode()) && (resolveType == GlobalLexicalVar || resolveType == GlobalLexicalVarWithVarInjectionChecks)) // TDZ check.
- linkCount++;
- if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
- // GlobalProperty/GlobalPropertyWithVarInjectionsCheck
- linkCount++; // emitLoadWithStructureCheck
-
- // GlobalLexicalVar
- bool needsTDZCheck = !isInitialization(getPutInfo.initializationMode());
- if (needsTDZCheck)
- linkCount++;
- linkCount++; // Notify write check.
-
- // GlobalLexicalVarWithVarInjectionsCheck
- linkCount++; // var injection check.
- if (needsTDZCheck)
- linkCount++;
- linkCount++; // Notify write check.
- }
- if (!linkCount)
- return;
- while (linkCount--)
- linkSlowCase(iter);
-
if (resolveType == ModuleVar) {
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_throw_strict_mode_readonly_property_write_error);
slowPathCall.call();