diff --git a/ChangeLog b/ChangeLog index b5632c292e..a7d7f939c1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -32,6 +32,7 @@ nRF5x: when connecting to other devices, allow a slave latency of 2 (might increase reliability) Fix `Got [ERASED] expecting X` when storage compacts while executing a function *in* storage on non-Bangle devices (fix #2431) JIT: Fix crashes when code got too big for simple 2-byte jump instructions (fix #2433) + JIT: Fixed/re-added while loops (and DO for huge loops) 2v19 : Fix Object.values/entries for numeric keys after 2v18 regression (fix #2375) nRF52: for SD>5 use static buffers for advertising and scan response data (#2367) diff --git a/README_JIT.md b/README_JIT.md index 5bfd0b1e59..43b0743a39 100644 --- a/README_JIT.md +++ b/README_JIT.md @@ -173,22 +173,19 @@ jit(); // prints 0,1,2,3,4 function jit() {"jit";for (var i=0;i<5;++i) print(i);} jit(); // prints 0,1,2,3,4 -/* -// WHILE is broken, so disabled for now - function jit() {"jit";while (0) {}} jit(); -E.setFlags({jitDebug:1}); function jit() {"jit";while (1) return 42;} jit()==42 function jit() {"jit";while (0) return 0;return 42;} jit()==42 +function jit(i) {"jit";while (i--) print(i);} +jit(5) // prints 4,3,2,1,0 + function jit() {"jit";while (i--) j++;} -i=1;j=0;jit(); // broken: Uncaught Error: Unable to assign value to non-reference ? -function jit() {"jit";while (0) print(5); print("Done"); } jit(); // ok -function jit() {"jit";while (1) print(5); print("Done"); } jit(); // Expecting a function to call, got Object (should print '5' forever) -*/ +i=1;j=0;jit(); // ok, does nothing +function jit() {"jit";while (0) print(5); print("Done"); } jit(); // prints 'Done' function jit() {"jit";do { print(i); } while (i--);} i=5;jit(); // prints 5,4,3,2,1,0 diff --git a/src/jsjit.c b/src/jsjit.c index aaea5cf588..4cf5efccb1 100644 --- a/src/jsjit.c +++ b/src/jsjit.c @@ -982,11 +982,15 @@ void jsjStatementFor() { void jsjStatementDoOrWhile(bool isWhile) { int codePosStart = jsjcGetByteCount(); if (isWhile) { // while loop - assert(0); - /*JSP_ASSERT_MATCH(LEX_R_WHILE); + JSP_ASSERT_MATCH(LEX_R_WHILE); DEBUG_JIT_EMIT("; WHILE condition\n"); JSP_MATCH('('); jsjExpression(); + if (jit.phase == JSJP_EMIT) { + // do this here so our stack counter stays at the right level + jsjPopAsBool(0); + jsjcCompareImm(0, 0); + } JSP_MATCH(')'); DEBUG_JIT_EMIT("; Parsing WHILE main block\n"); JsVar *oldBlock = jsjcStartBlock(); @@ -994,15 +998,13 @@ void jsjStatementDoOrWhile(bool isWhile) { JsVar *mainBlock = jsjcStopBlock(oldBlock); if (jit.phase == JSJP_EMIT) { DEBUG_JIT_EMIT("; WHILE condition jump\n"); - jsjPopAsBool(0); - jsjcCompareImm(0, 0); - jsjcBranchConditionalRelative(JSJAC_EQ, jsvGetStringLength(mainBlock) + 2, JSJC_NONE); + jsjcBranchConditionalRelative(JSJAC_EQ, jsvGetStringLength(mainBlock) + 4, JSJC_FORCE_4BYTE); DEBUG_JIT_EMIT("; WHILE Main block\n"); jsjcEmitBlock(mainBlock); DEBUG_JIT_EMIT("; WHILE jump back to condition\n"); - jsjcBranchRelative(codePosStart - (jsjcGetByteCount()), JSJC_NONE); + jsjcBranchRelative(codePosStart - (jsjcGetByteCount()+4), JSJC_FORCE_4BYTE); } - jsvUnLock(mainBlock);*/ + jsvUnLock(mainBlock); } else { // do..while loop JSP_ASSERT_MATCH(LEX_R_DO); DEBUG_JIT_EMIT("; DO Main block\n"); @@ -1015,7 +1017,7 @@ void jsjStatementDoOrWhile(bool isWhile) { if (jit.phase == JSJP_EMIT) { jsjPopAsBool(0); jsjcCompareImm(0, 0); - jsjcBranchConditionalRelative(JSJAC_NE, codePosStart - (jsjcGetByteCount()+2), JSJC_NONE); + jsjcBranchConditionalRelative(JSJAC_NE, codePosStart - (jsjcGetByteCount()+4), JSJC_FORCE_4BYTE); } } } @@ -1060,10 +1062,8 @@ void jsjStatement() { return jsjStatementVar(); } else if (lex->tk==LEX_R_IF) { return jsjStatementIf(); - } else if (lex->tk==LEX_R_DO) { - return jsjStatementDoOrWhile(false); - /*} else if (lex->tk==LEX_R_WHILE) { // FIXME - WHILE loop seems somehow broken, so is disabled for now - return jsjStatementDoOrWhile(true);*/ + } else if (lex->tk==LEX_R_DO || lex->tk==LEX_R_WHILE) { + return jsjStatementDoOrWhile(lex->tk==LEX_R_WHILE); } else if (lex->tk==LEX_R_FOR) { return jsjStatementFor(); /*} else if (lex->tk==LEX_R_TRY) {