diff options
-rw-r--r-- | src/qml/jit/qv4assemblercommon.cpp | 45 | ||||
-rw-r--r-- | src/qml/jit/qv4assemblercommon_p.h | 61 | ||||
-rw-r--r-- | src/qml/jit/qv4baselineassembler.cpp | 24 | ||||
-rw-r--r-- | src/qml/jit/qv4baselineassembler_p.h | 4 | ||||
-rw-r--r-- | src/qml/jit/qv4baselinejit.cpp | 12 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 10 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject_p.h | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 25 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtimeapi_p.h | 8 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4stackframe_p.h | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 6 | ||||
-rw-r--r-- | tests/auto/qml/ecmascripttests/TestExpectations | 31 |
12 files changed, 174 insertions, 62 deletions
diff --git a/src/qml/jit/qv4assemblercommon.cpp b/src/qml/jit/qv4assemblercommon.cpp index 0ae4da17fa..fadb9dce08 100644 --- a/src/qml/jit/qv4assemblercommon.cpp +++ b/src/qml/jit/qv4assemblercommon.cpp @@ -212,6 +212,13 @@ PlatformAssemblerCommon::Address PlatformAssemblerCommon::argStackAddress(int ar return Address(StackPointerRegister, offset * PointerSize); } +JSC::MacroAssemblerBase::Address PlatformAssemblerCommon::inArgStackAddress(int arg) +{ + int offset = arg - ArgInRegCount; + Q_ASSERT(offset >= 0); + return Address(FramePointerRegister, -(offset + 1) * PointerSize); +} + void PlatformAssemblerCommon::passAccumulatorAsArg(int arg) { #ifndef QT_NO_DEBUG @@ -329,12 +336,48 @@ void PlatformAssemblerCommon::callRuntime(const char *functionName, const void * } } -void JIT::PlatformAssemblerCommon::callRuntimeUnchecked(const char *functionName, const void *funcPtr) +void PlatformAssemblerCommon::callRuntimeUnchecked(const char *functionName, const void *funcPtr) { functions.insert(funcPtr, functionName); callAbsolute(funcPtr); } +void PlatformAssemblerCommon::tailCallRuntime(const char *functionName, const void *funcPtr) +{ + functions.insert(funcPtr, functionName); + setTailCallArg(EngineRegister, 1); + setTailCallArg(CppStackFrameRegister, 0); + freeStackSpace(); + generatePlatformFunctionExit(/*tailCall =*/ true); + jumpAbsolute(funcPtr); +} + +void PlatformAssemblerCommon::setTailCallArg(RegisterID src, int arg) +{ + if (arg < ArgInRegCount) + move(src, registerForArg(arg)); + else + storePtr(src, inArgStackAddress(arg)); +} + +JSC::MacroAssemblerBase::Address PlatformAssemblerCommon::jsAlloca(int slotCount) +{ + Address jsStackTopAddr(EngineRegister, offsetof(EngineBase, jsStackTop)); + RegisterID jsStackTop = AccumulatorRegisterValue; + loadPtr(jsStackTopAddr, jsStackTop); + addPtr(TrustedImm32(sizeof(Value) * slotCount), jsStackTop); + storePtr(jsStackTop, jsStackTopAddr); + return Address(jsStackTop, 0); +} + +void PlatformAssemblerCommon::storeInt32AsValue(int srcInt, Address destAddr) +{ + store32(TrustedImm32(srcInt), + Address(destAddr.base, destAddr.offset + QV4::Value::valueOffset())); + store32(TrustedImm32(int(QV4::Value::ValueTypeInternal::Integer)), + Address(destAddr.base, destAddr.offset + QV4::Value::tagOffset())); +} + } // JIT namespace } // QV4 namepsace diff --git a/src/qml/jit/qv4assemblercommon_p.h b/src/qml/jit/qv4assemblercommon_p.h index d64b9d0e5d..cbbd6464d9 100644 --- a/src/qml/jit/qv4assemblercommon_p.h +++ b/src/qml/jit/qv4assemblercommon_p.h @@ -116,14 +116,15 @@ public: move(Arg1Reg, EngineRegister); } - void generatePlatformFunctionExit() + void generatePlatformFunctionExit(bool tailCall = false) { pop(EngineRegister); pop(CppStackFrameRegister); pop(JSStackFrameRegister); pop(); // exceptionHandler pop(FramePointerRegister); - ret(); + if (!tailCall) + ret(); } void callAbsolute(const void *funcPtr) @@ -132,6 +133,12 @@ public: call(ScratchRegister); } + void jumpAbsolute(const void *funcPtr) + { + move(TrustedImmPtr(funcPtr), ScratchRegister); + jump(ScratchRegister); + } + void pushAligned(RegisterID reg) { subPtr(TrustedImm32(PointerSize), StackPointerRegister); @@ -195,14 +202,15 @@ public: move(Arg1Reg, EngineRegister); } - void generatePlatformFunctionExit() + void generatePlatformFunctionExit(bool tailCall = false) { pop(EngineRegister); pop(CppStackFrameRegister); pop(JSStackFrameRegister); pop(); // exceptionHandler pop(FramePointerRegister); - ret(); + if (!tailCall) + ret(); } void callAbsolute(const void *funcPtr) @@ -213,6 +221,12 @@ public: addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister); } + void jumpAbsolute(const void *funcPtr) + { + move(TrustedImmPtr(funcPtr), ScratchRegister); + jump(ScratchRegister); + } + void pushAligned(RegisterID reg) { subPtr(TrustedImm32(PointerSize), StackPointerRegister); @@ -280,7 +294,7 @@ public: loadPtr(Address(FramePointerRegister, 3 * PointerSize), EngineRegister); } - void generatePlatformFunctionExit() + void generatePlatformFunctionExit(bool tailCall = false) { addPtr(TrustedImm32(8), StackPointerRegister); pop(EngineRegister); @@ -288,7 +302,8 @@ public: pop(JSStackFrameRegister); pop(); // exceptionHandler pop(RegisterID::ebp); - ret(); + if (!tailCall) + ret(); } void callAbsolute(const void *funcPtr) @@ -297,6 +312,12 @@ public: call(ScratchRegister); } + void jumpAbsolute(const void *funcPtr) + { + move(TrustedImmPtr(funcPtr), ScratchRegister); + jump(ScratchRegister); + } + void pushAligned(RegisterID reg) { subPtr(TrustedImm32(PointerSize), StackPointerRegister); @@ -375,13 +396,14 @@ public: move(Arg1Reg, EngineRegister); } - void generatePlatformFunctionExit() + void generatePlatformFunctionExit(bool tailCall = false) { move(AccumulatorRegister, ReturnValueRegister); popPair(EngineRegister, CppStackFrameRegister); popPair(JSStackFrameRegister, AccumulatorRegister); popPair(JSC::ARM64Registers::fp, JSC::ARM64Registers::lr); - ret(); + if (!tailCall) + ret(); } void callAbsolute(const void *funcPtr) @@ -390,6 +412,12 @@ public: call(ScratchRegister); } + void jumpAbsolute(const void *funcPtr) + { + move(TrustedImmPtr(funcPtr), ScratchRegister); + jump(ScratchRegister); + } + void pushAligned(RegisterID reg) { pushToSave(reg); @@ -462,7 +490,7 @@ public: move(Arg1Reg, EngineRegister); } - void generatePlatformFunctionExit() + void generatePlatformFunctionExit(bool tailCall = false) { move(AccumulatorRegisterValue, ReturnValueRegisterValue); move(AccumulatorRegisterTag, ReturnValueRegisterTag); @@ -476,7 +504,8 @@ public: pop(); // exceptionHandler pop(FramePointerRegister); pop(JSC::ARMRegisters::lr); - ret(); + if (!tailCall) + ret(); } void callAbsolute(const void *funcPtr) @@ -485,6 +514,12 @@ public: call(dataTempRegister); } + void jumpAbsolute(const void *funcPtr) + { + move(TrustedImmPtr(funcPtr), dataTempRegister); + jump(dataTempRegister); + } + void pushAligned(RegisterID reg) { subPtr(TrustedImm32(PointerSize), StackPointerRegister); @@ -663,11 +698,15 @@ public: void passInt32AsArg(int value, int arg); void callRuntime(const char *functionName, const void *funcPtr); void callRuntimeUnchecked(const char *functionName, const void *funcPtr); - + void tailCallRuntime(const char *functionName, const void *funcPtr); + void setTailCallArg(RegisterID src, int arg); + Address jsAlloca(int slotCount); + void storeInt32AsValue(int srcInt, Address destAddr); private: void passAccumulatorAsArg_internal(int arg, bool doPush); static Address argStackAddress(int arg); + static Address inArgStackAddress(int arg); private: const Value* constantTable; diff --git a/src/qml/jit/qv4baselineassembler.cpp b/src/qml/jit/qv4baselineassembler.cpp index d53bb84827..f6b745632b 100644 --- a/src/qml/jit/qv4baselineassembler.cpp +++ b/src/qml/jit/qv4baselineassembler.cpp @@ -1446,7 +1446,29 @@ void BaselineAssembler::callRuntime(const char *functionName, const void *funcPt void BaselineAssembler::saveAccumulatorInFrame() { pasm()->storeAccumulator(PlatformAssembler::Address(PlatformAssembler::JSStackFrameRegister, - offsetof(CallData, accumulator))); + offsetof(CallData, accumulator))); +} + +static ReturnedValue TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing(CppStackFrame *frame, ExecutionEngine *engine) +{ + return Runtime::method_tailCall(frame, engine); +} + +void BaselineAssembler::jsTailCall(int func, int thisObject, int argc, int argv) +{ + Address tos = pasm()->jsAlloca(4); + + int32_t argcOffset = tos.offset + int32_t(sizeof(Value)) * Runtime::StackOffsets::tailCall_argc; + int32_t argvOffset = tos.offset + int32_t(sizeof(Value)) * Runtime::StackOffsets::tailCall_argv; + int32_t thisOffset = tos.offset + int32_t(sizeof(Value)) * Runtime::StackOffsets::tailCall_thisObject; + int32_t funcOffset = tos.offset + int32_t(sizeof(Value)) * Runtime::StackOffsets::tailCall_function; + + pasm()->storeInt32AsValue(argc, Address(tos.base, argcOffset)); + pasm()->storeInt32AsValue(argv, Address(tos.base, argvOffset)); + pasm()->moveReg(regAddr(thisObject), Address(tos.base, thisOffset)); + pasm()->moveReg(regAddr(func), Address(tos.base, funcOffset)); + pasm()->tailCallRuntime("TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing", + reinterpret_cast<void *>(TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing)); } void BaselineAssembler::checkException() diff --git a/src/qml/jit/qv4baselineassembler_p.h b/src/qml/jit/qv4baselineassembler_p.h index a2140ce47b..0aa508ae71 100644 --- a/src/qml/jit/qv4baselineassembler_p.h +++ b/src/qml/jit/qv4baselineassembler_p.h @@ -67,6 +67,9 @@ namespace JIT { callRuntime(JIT_STRINGIFY(function), \ reinterpret_cast<void *>(&function), \ destination) +#define GENERATE_TAIL_CALL(function) \ + tailCallRuntime(JIT_STRINGIFY(function), \ + reinterpret_cast<void *>(&function)) class BaselineAssembler { public: @@ -149,6 +152,7 @@ public: void passInt32AsArg(int value, int arg); void callRuntime(const char *functionName, const void *funcPtr, CallResultDestination dest); void saveAccumulatorInFrame(); + void jsTailCall(int func, int thisObject, int argc, int argv); // exception/context stuff void checkException(); diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp index 70d1672689..bbbe0c69c5 100644 --- a/src/qml/jit/qv4baselinejit.cpp +++ b/src/qml/jit/qv4baselinejit.cpp @@ -77,6 +77,8 @@ void BaselineJIT::generate() #define STORE_ACC() as->saveAccumulatorInFrame() #define BASELINEJIT_GENERATE_RUNTIME_CALL(function, destination) \ as->GENERATE_RUNTIME_CALL(function, destination) +#define BASELINEJIT_GENERATE_TAIL_CALL(function) \ + as->GENERATE_TAIL_CALL(function) void BaselineJIT::generate_Ret() { @@ -555,17 +557,9 @@ void BaselineJIT::generate_CallWithSpread(int func, int thisObject, int argc, in void BaselineJIT::generate_TailCall(int func, int thisObject, int argc, int argv) { STORE_IP(); - as->prepareCallWithArgCount(5); - as->passInt32AsArg(argc, 4); - as->passJSSlotAsArg(argv, 3); - as->passJSSlotAsArg(thisObject, 2); - as->passJSSlotAsArg(func, 1); - as->passEngineAsArg(0); - BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_tailCall, CallResultDestination::InAccumulator); - as->checkException(); + as->jsTailCall(func, thisObject, argc, argv); } - void BaselineJIT::generate_Construct(int func, int argc, int argv) { STORE_IP(); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index f6b279ddaf..93cc55f8ad 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -498,7 +498,7 @@ ReturnedValue ArrowFunction::virtualCall(const FunctionObject *fo, const Value * { ExecutionEngine *engine = fo->engine(); CppStackFrame frame; - frame.init(engine, fo->function(), argv, argc); + frame.init(engine, fo->function(), argv, argc, true); frame.setupJSFrame(engine->jsStackTop, *fo, fo->scope(), thisObject ? *thisObject : Value::undefinedValue(), Value::undefinedValue()); @@ -506,7 +506,12 @@ ReturnedValue ArrowFunction::virtualCall(const FunctionObject *fo, const Value * frame.push(); engine->jsStackTop += frame.requiredJSStackFrameSize(); - ReturnedValue result = Moth::VME::exec(&frame, engine); + ReturnedValue result; + + do { + frame.pendingTailCall = false; + result = Moth::VME::exec(&frame, engine); + } while (frame.pendingTailCall); frame.pop(); @@ -530,6 +535,7 @@ void Heap::ArrowFunction::init(QV4::ExecutionContext *scope, Function *function, Q_ASSERT(internalClass && internalClass->verifyIndex(s.engine->id_length()->propertyKey(), Index_Length)); setProperty(s.engine, Index_Length, Value::fromInt32(int(function->compiledFunction->length))); + canBeTailCalled = true; } void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function) diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index b08b333411..e03d49c74d 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -71,7 +71,8 @@ namespace Heap { Member(class, Pointer, ExecutionContext *, scope) \ Member(class, NoMark, Function *, function) \ Member(class, NoMark, VTable::Call, jsCall) \ - Member(class, NoMark, VTable::CallAsConstructor, jsConstruct) + Member(class, NoMark, VTable::CallAsConstructor, jsConstruct) \ + Member(class, NoMark, bool, canBeTailCalled) DECLARE_HEAP_OBJECT(FunctionObject, Object) { DECLARE_MARKOBJECTS(FunctionObject); @@ -175,6 +176,7 @@ struct Q_QML_EXPORT FunctionObject: Object { V4_NEEDS_DESTROY enum { NInlineProperties = 1 }; + bool canBeTailCalled() const { return d()->canBeTailCalled; } Heap::ExecutionContext *scope() const { return d()->scope; } Function *function() const { return d()->function; } diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 470629bd1f..66cd06ee1f 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1536,13 +1536,32 @@ ReturnedValue Runtime::method_constructWithSpread(ExecutionEngine *engine, const return static_cast<const FunctionObject &>(function).callAsConstructor(arguments.argv, arguments.argc, &newTarget); } -ReturnedValue Runtime::method_tailCall(ExecutionEngine *engine, const Value &function, const Value &thisObject, Value *argv, int argc) +ReturnedValue Runtime::method_tailCall(CppStackFrame *frame, ExecutionEngine *engine) { - //### unwinding the stack, etc, is done in a subsequent patch + // IMPORTANT! The JIT assumes that this method has the same amount (or less) arguments than + // the jitted function, so it can safely do a tail call. + + Value *tos = engine->jsStackTop; + const Value &function = tos[StackOffsets::tailCall_function]; + const Value &thisObject = tos[StackOffsets::tailCall_thisObject]; + Value *argv = reinterpret_cast<Value *>(frame->jsFrame) + tos[StackOffsets::tailCall_argv].int_32(); + int argc = tos[StackOffsets::tailCall_argc].int_32(); + if (!function.isFunctionObject()) return engine->throwTypeError(); - return static_cast<const FunctionObject &>(function).call(&thisObject, argv, argc); + const FunctionObject &fo = static_cast<const FunctionObject &>(function); + if (!frame->callerCanHandleTailCall || !fo.canBeTailCalled() || engine->debugger()) { + // Cannot tailcall, do a normal call: + return fo.call(&thisObject, argv, argc); + } + + memcpy(frame->jsFrame->args, argv, argc * sizeof(Value)); + frame->init(engine, fo.function(), frame->jsFrame->args, argc, frame->callerCanHandleTailCall); + frame->setupJSFrame(frame->savedStackTop, fo, fo.scope(), thisObject, Primitive::undefinedValue()); + engine->jsStackTop = frame->savedStackTop + frame->requiredJSStackFrameSize(); + frame->pendingTailCall = true; + return Encode::undefined(); } void Runtime::method_throwException(ExecutionEngine *engine, const Value &value) diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h index 826b371c1d..d64178a72f 100644 --- a/src/qml/jsruntime/qv4runtimeapi_p.h +++ b/src/qml/jsruntime/qv4runtimeapi_p.h @@ -101,7 +101,7 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> { F(ReturnedValue, callWithReceiver, (ExecutionEngine *engine, const Value &func, const Value *thisObject, Value *argv, int argc)) \ F(ReturnedValue, callPossiblyDirectEval, (ExecutionEngine *engine, Value *argv, int argc)) \ F(ReturnedValue, callWithSpread, (ExecutionEngine *engine, const Value &func, const Value &thisObject, Value *argv, int argc)) \ - F(ReturnedValue, tailCall, (ExecutionEngine *engine, const Value &func, const Value &thisObject, Value *argv, int argc)) \ + F(ReturnedValue, tailCall, (CppStackFrame *frame, ExecutionEngine *engine)) \ \ /* construct */ \ F(ReturnedValue, construct, (ExecutionEngine *engine, const Value &func, const Value &newTarget, Value *argv, int argc)) \ @@ -234,6 +234,12 @@ struct Q_QML_PRIVATE_EXPORT Runtime { FOR_EACH_RUNTIME_METHOD(RUNTIME_METHOD) #undef RUNTIME_METHOD + struct StackOffsets { + static const int tailCall_function = -1; + static const int tailCall_thisObject = -2; + static const int tailCall_argv = -3; + static const int tailCall_argc = -4; + }; }; static_assert(std::is_standard_layout<Runtime>::value, "Runtime needs to be standard layout in order for us to be able to use offsetof"); diff --git a/src/qml/jsruntime/qv4stackframe_p.h b/src/qml/jsruntime/qv4stackframe_p.h index dd68c29a88..a97ae0e7c9 100644 --- a/src/qml/jsruntime/qv4stackframe_p.h +++ b/src/qml/jsruntime/qv4stackframe_p.h @@ -123,8 +123,10 @@ struct Q_QML_EXPORT CppStackFrame { const char *unwindLabel; int unwindLevel; bool yieldIsIterator; + bool callerCanHandleTailCall; + bool pendingTailCall; - void init(EngineBase *engine, Function *v4Function, const Value *argv, int argc) { + void init(EngineBase *engine, Function *v4Function, const Value *argv, int argc, bool callerCanHandleTailCall = false) { this->engine = engine; this->v4Function = v4Function; @@ -136,6 +138,8 @@ struct Q_QML_EXPORT CppStackFrame { unwindLabel = nullptr; unwindLevel = 0; yieldIsIterator = false; + this->callerCanHandleTailCall = callerCanHandleTailCall; + pendingTailCall = false; } void push() { diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 7fd7be8e38..5d95c8c2ab 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -778,7 +778,11 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(TailCall) STORE_IP(); - acc = Runtime::method_tailCall(engine, STACK_VALUE(func), STACK_VALUE(thisObject), stack + argv, argc); + *engine->jsAlloca(1) = Primitive::fromInt32(argc); + *engine->jsAlloca(1) = Primitive::fromInt32(argv); + *engine->jsAlloca(1) = STACK_VALUE(thisObject); + *engine->jsAlloca(1) = STACK_VALUE(func); + return Runtime::method_tailCall(frame, engine); CHECK_EXCEPTION; MOTH_END_INSTR(TailCall) diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations index 6236fe5036..f5a31856b1 100644 --- a/tests/auto/qml/ecmascripttests/TestExpectations +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -536,12 +536,6 @@ language/expressions/call/eval-spread-empty-leading.js fails language/expressions/call/eval-spread-empty-trailing.js fails language/expressions/call/eval-spread.js fails language/expressions/call/scope-lex-open.js fails -language/expressions/call/tco-call-args.js strictFails -language/expressions/call/tco-member-args.js strictFails -language/expressions/call/tco-non-eval-function-dynamic.js sloppyFails -language/expressions/call/tco-non-eval-function.js sloppyFails -language/expressions/call/tco-non-eval-global.js sloppyFails -language/expressions/call/tco-non-eval-with.js sloppyFails language/expressions/class/gen-meth-dflt-params-ref-later.js fails language/expressions/class/gen-meth-dflt-params-ref-self.js fails language/expressions/class/gen-meth-static-dflt-params-ref-later.js fails @@ -557,7 +551,6 @@ language/expressions/class/scope-setter-paramsbody-var-open.js fails language/expressions/class/scope-static-gen-meth-paramsbody-var-open.js fails language/expressions/class/scope-static-meth-paramsbody-var-open.js fails language/expressions/class/scope-static-setter-paramsbody-var-open.js fails -language/expressions/comma/tco-final.js strictFails language/expressions/compound-assignment/S11.13.2_A5.10_T1.js sloppyFails language/expressions/compound-assignment/S11.13.2_A5.10_T2.js sloppyFails language/expressions/compound-assignment/S11.13.2_A5.10_T3.js sloppyFails @@ -636,8 +629,6 @@ language/expressions/compound-assignment/S11.13.2_A7.7_T4.js fails language/expressions/compound-assignment/S11.13.2_A7.8_T4.js fails language/expressions/compound-assignment/S11.13.2_A7.9_T4.js fails language/expressions/delete/super-property.js fails -language/expressions/conditional/tco-cond.js strictFails -language/expressions/conditional/tco-pos.js strictFails language/expressions/function/arguments-with-arguments-fn.js sloppyFails language/expressions/function/arguments-with-arguments-lex.js sloppyFails language/expressions/function/dflt-params-ref-later.js fails @@ -672,8 +663,6 @@ language/expressions/generators/yield-as-identifier-in-nested-function.js sloppy language/expressions/generators/yield-as-literal-property-name.js fails language/expressions/generators/yield-as-property-name.js fails language/expressions/generators/yield-identifier-non-strict.js sloppyFails -language/expressions/logical-and/tco-right.js strictFails -language/expressions/logical-or/tco-right.js strictFails language/expressions/object/let-non-strict-access.js sloppyFails language/expressions/object/let-non-strict-syntax.js sloppyFails language/expressions/object/method-definition/gen-meth-dflt-params-ref-later.js fails @@ -731,12 +720,10 @@ language/expressions/tagged-template/cache-eval-inner-function.js fails language/expressions/tagged-template/cache-same-site-top-level.js fails language/expressions/tagged-template/cache-same-site.js fails language/expressions/tagged-template/invalid-escape-sequences.js fails -language/expressions/tagged-template/tco-call.js strictFails language/expressions/tagged-template/tco-member.js strictFails language/expressions/tagged-template/template-object-frozen-non-strict.js sloppyFails language/expressions/tagged-template/template-object-frozen-strict.js strictFails language/expressions/tagged-template/template-object.js fails -language/expressions/tco-pos.js strictFails language/expressions/template-literal/tv-character-escape-sequence.js fails language/expressions/template-literal/tv-hex-escape-sequence.js fails language/expressions/template-literal/tv-line-continuation.js fails @@ -771,8 +758,6 @@ language/statements/async-function/cptn-decl.js fails language/statements/async-function/declaration-returns-promise.js fails language/statements/async-function/evaluation-body.js fails language/statements/async-function/syntax-declaration-line-terminators-allowed.js fails -language/statements/block/tco-stmt-list.js strictFails -language/statements/block/tco-stmt.js strictFails language/statements/class/constructor-inferred-observable-iteration.js fails language/statements/class/cptn-decl.js fails language/statements/class/definition/class-method-returns-promise.js fails @@ -804,7 +789,6 @@ language/statements/class/subclass/bound-function.js fails language/statements/class/subclass/builtin-objects/Promise/regular-subclassing.js fails language/statements/class/subclass/builtin-objects/Promise/super-must-be-called.js fails language/statements/class/subclass/default-constructor-spread-override.js fails -language/statements/do-while/tco-body.js strictFails language/statements/for-in/head-lhs-let.js sloppyFails language/statements/for-in/head-var-bound-names-let.js sloppyFails language/statements/for-in/identifier-let-allowed-as-lefthandside-expression-not-strict.js sloppyFails @@ -832,10 +816,6 @@ language/statements/for-of/head-var-bound-names-let.js sloppyFails language/statements/for-of/iterator-next-reference.js fails language/statements/for/head-lhs-let.js sloppyFails language/statements/for/scope-body-lex-open.js fails -language/statements/for/tco-const-body.js strictFails -language/statements/for/tco-let-body.js strictFails -language/statements/for/tco-lhs-body.js strictFails -language/statements/for/tco-var-body.js strictFails language/statements/function/13.2-30-s.js fails language/statements/function/S13_A15_T4.js sloppyFails language/statements/function/arguments-with-arguments-fn.js sloppyFails @@ -865,23 +845,12 @@ language/statements/generators/yield-as-identifier-in-nested-function.js sloppyF language/statements/generators/yield-as-literal-property-name.js fails language/statements/generators/yield-as-property-name.js fails language/statements/generators/yield-identifier-non-strict.js sloppyFails -language/statements/if/tco-else-body.js strictFails -language/statements/if/tco-if-body.js strictFails -language/statements/labeled/tco.js strictFails language/statements/let/block-local-closure-set-before-initialization.js fails language/statements/let/function-local-closure-set-before-initialization.js fails language/statements/let/global-closure-set-before-initialization.js fails -language/statements/return/tco.js strictFails -language/statements/switch/tco-case-body-dflt.js strictFails -language/statements/switch/tco-case-body.js strictFails -language/statements/switch/tco-dftl-body.js strictFails language/statements/throw/S12.13_A2_T6.js strictFails language/statements/try/S12.14_A18_T6.js strictFails language/statements/try/scope-catch-block-lex-open.js fails -language/statements/try/tco-catch-finally.js strictFails -language/statements/try/tco-catch.js strictFails -language/statements/try/tco-finally.js strictFails language/statements/variable/binding-resolution.js sloppyFails -language/statements/while/tco-body.js strictFails language/statements/with/unscopables-inc-dec.js sloppyFails language/types/reference/put-value-prop-base-primitive.js strictFails |