If executing from storage, work out line numbers and print filename for Errors

Bangle.js: Don't store line numbers in functions - no need when execing from flash
This commit is contained in:
Gordon Williams 2021-10-25 12:52:06 +01:00
parent 8ec757da9a
commit 03d147ae1f
12 changed files with 91 additions and 17 deletions

View File

@ -54,6 +54,8 @@
Bangle.js: Ensure builtin E.show* (and fake LEDs) wake the LCD up
Storage check now *only* happens on first boot
Ensure __FILE__ is set by the time bootcode runs
If executing from storage, work out line numbers and print filename for Errors
Bangle.js: Don't store line numbers in functions - no need when execing from flash
2v10 : Bangle.js: Improved HRM calculations - swapped autocorrelation for bandpass filter
Bangle.js: Significantly improved step counting algorithm using bandpass filter (fix #1846)

View File

@ -136,6 +136,7 @@ This is a partial list of definitions that can be added in a `BOARD.py` file's `
* `ESPR_NO_LOADING_SCREEN` - Bangle.js, don't show a 'loading' screen when loading a new app
* `ESPR_BOOTLOADER_SPIFLASH` - Allow bootloader to flash direct from a file in SPI flash storage
* `ESPR_BANGLE_UNISTROKE` - Build in 'unistroke' touch gesture recognition
* `ESPR_NO_LINE_NUMBERS` - disable storing and reporting of Line Numbers. Usually these take 1 var per function, but if we're executing a function from flash we can just work it out from the file when needed
### chip

View File

@ -47,6 +47,7 @@ info = {
'DEFINES+=-DDUMP_IGNORE_VARIABLES=\'"g\\0"\'',
'DEFINES+=-DUSE_FONT_6X8 -DGRAPHICS_PALETTED_IMAGES -DGRAPHICS_ANTIALIAS',
'DEFINES+=-DNO_DUMP_HARDWARE_INITIALISATION', # don't dump hardware init - not used and saves 1k of flash
'DEFINES += -DESPR_NO_LINE_NUMBERS=1', # we execute mainly from flash, so line numbers can be worked out
'DEFINES+=-DAPP_TIMER_OP_QUEUE_SIZE=6', # Bangle.js accelerometer poll handler needs something else in queue size
'DFU_PRIVATE_KEY=targets/nrf5x_dfu/dfu_private_key.pem',
'DFU_SETTINGS=--application-version 0xff --hw-version 52 --sd-req 0x8C,0x91',

View File

@ -54,6 +54,7 @@ info = {
'DEFINES+=-DDUMP_IGNORE_VARIABLES=\'"g\\0"\'',
'DEFINES+=-DUSE_FONT_6X8 -DGRAPHICS_PALETTED_IMAGES',
'DEFINES+=-DNO_DUMP_HARDWARE_INITIALISATION', # don't dump hardware init - not used and saves 1k of flash
'DEFINES += -DESPR_NO_LINE_NUMBERS=1', # we execute mainly from flash, so line numbers can be worked out
'INCLUDE += -I$(ROOT)/libs/banglejs -I$(ROOT)/libs/misc',
'WRAPPERSOURCES += libs/banglejs/jswrap_bangle.c',
'WRAPPERSOURCES += libs/graphics/jswrap_font_6x15.c',

View File

@ -39,6 +39,7 @@ info = {
'DEFINES += -DSPIFLASH_BASE=0x8000000 -DSPIFLASH_LENGTH=4194304',
# 'DEFINES+=-DCUSTOM_GETBATTERY=jswrap_banglejs_getBattery',
'DEFINES+=-DDUMP_IGNORE_VARIABLES=\'"g\\0"\'',
'DEFINES += -DESPR_NO_LINE_NUMBERS=1', # we execute mainly from flash, so line numbers can be worked out
'DEFINES+=-DUSE_FONT_6X8 -DGRAPHICS_PALETTED_IMAGES -DGRAPHICS_ANTIALIAS',
'INCLUDE += -I$(ROOT)/libs/banglejs -I$(ROOT)/libs/misc',
'WRAPPERSOURCES += libs/banglejs/jswrap_bangle.c',

View File

@ -39,6 +39,7 @@ info = {
'DEFINES += -DSPIFLASH_BASE=0x8000000 -DSPIFLASH_LENGTH=8388608',
# 'DEFINES+=-DCUSTOM_GETBATTERY=jswrap_banglejs_getBattery',
'DEFINES+=-DDUMP_IGNORE_VARIABLES=\'"g\\0"\'',
'DEFINES += -DESPR_NO_LINE_NUMBERS=1', # we execute mainly from flash, so line numbers can be worked out
'DEFINES+=-DUSE_FONT_6X8 -DGRAPHICS_PALETTED_IMAGES',
'INCLUDE += -I$(ROOT)/libs/banglejs -I$(ROOT)/libs/misc',
'WRAPPERSOURCES += libs/banglejs/jswrap_bangle.c',

View File

@ -571,6 +571,38 @@ uint32_t jsfFindFile(JsfFileName name, JsfFileHeader *returnedHeader) {
return a;
}
static uint32_t jsfBankFindFileFromAddr(uint32_t bankAddress, uint32_t bankEndAddress, uint32_t containsAddr, JsfFileHeader *returnedHeader) {
uint32_t addr = bankAddress;
JsfFileHeader header;
memset(&header,0,sizeof(JsfFileHeader));
if (jsfGetFileHeader(addr, &header, false)) do {
uint32_t endOfFile = addr + (uint32_t)sizeof(JsfFileHeader) + jsfGetFileSize(&header);
if ((header.name.firstChars != 0) && // not been replaced
(addr<=containsAddr && containsAddr<=endOfFile)) {
// Now load the whole header (with name) and check properly
jsfGetFileHeader(addr, &header, true);
if (returnedHeader)
*returnedHeader = header;
return addr+(uint32_t)sizeof(JsfFileHeader);
}
} while (jsfGetNextFileHeader(&addr, &header, GNFH_GET_ALL|GNFH_READ_ONLY_FILENAME_START)); // still only get first 4 chars of name
return 0;
}
uint32_t jsfFindFileFromAddr(uint32_t containsAddr, JsfFileHeader *returnedHeader) {
if (containsAddr>=JSF_START_ADDRESS && containsAddr<=JSF_END_ADDRESS) {
uint32_t a = jsfBankFindFileFromAddr(JSF_START_ADDRESS, JSF_END_ADDRESS, containsAddr, returnedHeader);
if (a) return a;
}
#ifdef JSF_BANK2_START_ADDRESS
if (containsAddr>=JSF_BANK2_START_ADDRESS && containsAddr<=JSF_BANK2_END_ADDRESS) {
uint32_t a = jsfBankFindFileFromAddr(JSF_BANK2_START_ADDRESS, JSF_BANK2_END_ADDRESS, containsAddr, returnedHeader);
if (a) return a;
}
#endif
return 0;
}
static void jsfBankDebugFiles(uint32_t addr) {
uint32_t pageAddr = 0, pageLen = 0, pageEndAddr = 0;
@ -698,25 +730,14 @@ JsVar *jsfReadFile(JsfFileName name, int offset, int length) {
if (length<=0) return jsvNewFromEmptyString();
// now increment address by offset
addr += (uint32_t)offset;
return jsvAddressToVar(addr, (uint32_t)length);
}
JsVar* jsvAddressToVar(size_t addr, uint32_t length) {
if (length<=0) return jsvNewFromEmptyString();
size_t mappedAddr = jshFlashGetMemMapAddress((size_t)addr);
#ifdef SPIFLASH_BASE // if using SPI flash it can't be memory-mapped
if (!mappedAddr) {
/*JsVar *v = jsvNewStringOfLength(length, NULL);
if (v) {
JsvStringIterator it;
jsvStringIteratorNew(&it, v, 0);
while (length && jsvStringIteratorHasChar(&it)) {
unsigned char *data;
unsigned int l = 0;
jsvStringIteratorGetPtrAndNext(&it, &data, &l);
jshFlashRead(data, addr, l);
addr += l;
length -= l;
}
jsvStringIteratorFree(&it);
}
return v;*/
return jsvNewFlashString((char*)(size_t)addr, (size_t)length);
}
#endif

View File

@ -53,6 +53,10 @@ uint32_t jsfGetFileSize(JsfFileHeader *header);
JsfFileFlags jsfGetFileFlags(JsfFileHeader *header);
/// Find a 'file' in the memory store. Return the address of data start (and header if returnedHeader!=0). Returns 0 if not found
uint32_t jsfFindFile(JsfFileName name, JsfFileHeader *returnedHeader);
/// Find a 'file' in the memory store that contains this address. Return the address of data start (and header if returnedHeader!=0). Returns 0 if not found
uint32_t jsfFindFileFromAddr(uint32_t containsAddr, JsfFileHeader *returnedHeader);
/// Given an address in memory (or flash) return the correct JsVar to access it
JsVar* jsvAddressToVar(size_t addr, uint32_t length);
/// Return the contents of a file as a memory mapped var
JsVar *jsfReadFile(JsfFileName name, int offset, int length);
/// Write a file. For simple stuff just leave offset and size as 0

View File

@ -2487,9 +2487,12 @@ void jsiDebuggerLoop() {
char lineStr[9];
// Get a string fo the form '1234 ' for the line number
// ... but only if the line number was set, otherwise use spaces
#ifndef ESPR_NO_LINE_NUMBERS
if (lex->lineNumberOffset) {
itostr((JsVarInt)jslGetLineNumber() + (JsVarInt)lex->lineNumberOffset - 1, lineStr, 10);
} else {
} else
#endif
{
lineStr[0]=0;
}
size_t lineLen = strlen(lineStr);

View File

@ -12,6 +12,9 @@
* ----------------------------------------------------------------------------
*/
#include "jslex.h"
#ifndef SAVE_ON_FLASH
#include "jsflash.h"
#endif
JsLex *lex;
@ -676,7 +679,9 @@ void jslInit(JsVar *var) {
lex->tokenLastStart = 0;
lex->tokenl = 0;
lex->tokenValue = 0;
#ifndef ESPR_NO_LINE_NUMBERS
lex->lineNumberOffset = 0;
#endif
// set up iterator
jsvStringIteratorNew(&lex->it, lex->sourceVar, 0);
jsvUnLock(lex->it.var); // see jslGetNextCh
@ -1086,9 +1091,26 @@ void jslPrintTokenisedString(JsVar *code, vcbprintf_callback user_callback, void
void jslPrintPosition(vcbprintf_callback user_callback, void *user_data, size_t tokenPos) {
size_t line,col;
#ifndef SAVE_ON_FLASH
if (jsvIsNativeString(lex->sourceVar) || jsvIsFlashString(lex->sourceVar)) {
uint32_t stringAddr = (uint32_t)lex->sourceVar->varData.nativeStr.ptr;
JsfFileHeader header;
uint32_t fileAddr = jsfFindFileFromAddr(stringAddr, &header);
if (fileAddr) {
JsVar *fileStr = jsvAddressToVar(fileAddr, jsfGetFileSize(&header));
jsvGetLineAndCol(fileStr, tokenPos + stringAddr - fileAddr, &line, &col);
JsVar *name = jsfVarFromName(header.name);
cbprintf(user_callback, user_data,"line %d col %d in %v\n", line, col, name);
jsvUnLock2(fileStr,name);
return;
}
}
#endif
jsvGetLineAndCol(lex->sourceVar, tokenPos, &line, &col);
#ifndef ESPR_NO_LINE_NUMBERS
if (lex->lineNumberOffset)
line += (size_t)lex->lineNumberOffset - 1;
#endif
cbprintf(user_callback, user_data, "line %d col %d\n", line, col);
}

View File

@ -125,9 +125,11 @@ typedef struct JsLex
JsVar *tokenValue; ///< JsVar containing the current token - used only for strings/regex
unsigned char tokenl; ///< the current length of token
#ifndef ESPR_NO_LINE_NUMBERS
/** Amount we add to the line number when we're reporting to the user
* 1-based, so 0 means NO LINE NUMBER KNOWN */
uint16_t lineNumberOffset;
#endif
/* Where we get our data from...
*

View File

@ -346,12 +346,14 @@ NO_INLINE bool jspeFunctionDefinitionInternal(JsVar *funcVar, bool expressionOnl
JSP_ASSERT_MATCH(LEX_R_RETURN);
}
}
#ifndef ESPR_NO_LINE_NUMBERS
// Get the line number (if needed)
JsVarInt lineNumber = 0;
if (funcVar && lex->lineNumberOffset && !(forcePretokenise||jsfGetFlag(JSF_PRETOKENISE))) {
// jslGetLineNumber is slow, so we only do it if we have debug info
lineNumber = (JsVarInt)jslGetLineNumber() + (JsVarInt)lex->lineNumberOffset - 1;
}
#endif
// Get the code - parse it and figure out where it stops
JslCharPos funcBegin;
jslSkipWhiteSpace();
@ -402,6 +404,7 @@ NO_INLINE bool jspeFunctionDefinitionInternal(JsVar *funcVar, bool expressionOnl
if (funcScopeVar) {
jsvUnLock2(jsvAddNamedChild(funcVar, funcScopeVar, JSPARSE_FUNCTION_SCOPE_NAME), funcScopeVar);
}
#ifndef ESPR_NO_LINE_NUMBERS
// If we've got a line number, add a var for it
if (lineNumber) {
JsVar *funcLineNumber = jsvNewFromInteger(lineNumber);
@ -409,6 +412,7 @@ NO_INLINE bool jspeFunctionDefinitionInternal(JsVar *funcVar, bool expressionOnl
jsvUnLock2(jsvAddNamedChild(funcVar, funcLineNumber, JSPARSE_FUNCTION_LINENUMBER_NAME), funcLineNumber);
}
}
#endif
}
jslCharPosFree(&funcBegin);
@ -629,7 +633,9 @@ NO_INLINE JsVar *jspeFunctionCall(JsVar *function, JsVar *functionName, JsVar *t
JsVar *functionScope = 0;
JsVar *functionCode = 0;
JsVar *functionInternalName = 0;
#ifndef ESPR_NO_LINE_NUMBERS
uint16_t functionLineNumber = 0;
#endif
/** NOTE: We expect that the function object will have:
*
@ -695,7 +701,10 @@ NO_INLINE JsVar *jspeFunctionCall(JsVar *function, JsVar *functionName, JsVar *t
else if (jsvIsStringEqual(param, JSPARSE_FUNCTION_THIS_NAME)) {
jsvUnLock(thisVar);
thisVar = jsvSkipName(param);
} else if (jsvIsStringEqual(param, JSPARSE_FUNCTION_LINENUMBER_NAME)) functionLineNumber = (uint16_t)jsvGetIntegerAndUnLock(jsvSkipName(param));
}
#ifndef ESPR_NO_LINE_NUMBERS
else if (jsvIsStringEqual(param, JSPARSE_FUNCTION_LINENUMBER_NAME)) functionLineNumber = (uint16_t)jsvGetIntegerAndUnLock(jsvSkipName(param));
#endif
else if (jsvIsFunctionParameter(param)) {
JsVar *defaultVal = jsvSkipName(param);
jsvAddFunctionParameter(functionRoot, jsvNewFromStringVar(param,1,JSVAPPENDSTRINGVAR_MAXLENGTH), defaultVal);
@ -759,7 +768,9 @@ NO_INLINE JsVar *jspeFunctionCall(JsVar *function, JsVar *functionName, JsVar *t
JsLex newLex;
JsLex *oldLex = jslSetLex(&newLex);
jslInit(functionCode);
#ifndef ESPR_NO_LINE_NUMBERS
newLex.lineNumberOffset = functionLineNumber;
#endif
JSP_SAVE_EXECUTE();
// force execute without any previous state
#ifdef USE_DEBUGGER
@ -2955,7 +2966,9 @@ JsVar *jspEvaluateExpressionVar(JsVar *str) {
assert(jsvIsString(str));
JsLex *oldLex = jslSetLex(&lex);
jslInit(str);
#ifndef ESPR_NO_LINE_NUMBERS
lex.lineNumberOffset = oldLex->lineNumberOffset;
#endif
// actually do the parsing
JsVar *v = jspeExpression();
@ -2973,7 +2986,9 @@ JsVar *jspEvaluateVar(JsVar *str, JsVar *scope, uint16_t lineNumberOffset) {
assert(jsvIsString(str));
JsLex *oldLex = jslSetLex(&lex);
jslInit(str);
#ifndef ESPR_NO_LINE_NUMBERS
lex.lineNumberOffset = lineNumberOffset;
#endif
JsExecInfo oldExecInfo = execInfo;