Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
eaac369d
Unverified
Commit
eaac369d
authored
Jul 22, 2019
by
Johny Mattsson
Committed by
GitHub
Jul 22, 2019
Browse files
LFS support for ESP32 NodeMCU (#2801)
* Port LFS from ESP8266 to ESP32
parent
7cb61a27
Changes
116
Show whitespace changes
Inline
Side-by-side
components/lua/lflash.c
0 → 100644
View file @
eaac369d
/*
** $Id: lflash.c
** See Copyright Notice in lua.h
*/
#define lflash_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lobject.h"
#include "lauxlib.h"
#include "lstate.h"
#include "lfunc.h"
#include "lflash.h"
#include "platform.h"
#include "vfs.h"
#include "uzlib.h"
#include "platform_wdt.h"
#include "esp_partition.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* Flash memory is a fixed memory addressable block that is serially allocated by the
* luac build process and the out image can be downloaded into SPIFSS and loaded into
* flash with a node.flash.load() command. See luac_cross/lflashimg.c for the build
* process.
*/
static
const
char
*
flashAddr
;
static
uint32_t
flashSize
;
static
uint32_t
flashAddrPhys
;
static
uint32_t
flashSector
;
static
uint32_t
curOffset
;
#define ALIGN(s) (((s)+sizeof(size_t)-1) & ((size_t) (- (signed) sizeof(size_t))))
#define ALIGN_BITS(s) (((uint32_t)s) & (sizeof(size_t)-1))
#define ALL_SET (~0)
#define FLASH_PAGE_SIZE INTERNAL_FLASH_SECTOR_SIZE
#define FLASH_PAGES (flashSize/FLASH_PAGE_SIZE)
#define READ_BLOCKSIZE 1024
#define WRITE_BLOCKSIZE 2048
#define DICTIONARY_WINDOW 16384
#define WORDSIZE (sizeof(int))
#define BITS_PER_WORD 32
#define WRITE_BLOCKS ((DICTIONARY_WINDOW/WRITE_BLOCKSIZE)+1)
#define WRITE_BLOCK_WORDS (WRITE_BLOCKSIZE/WORDSIZE)
struct
INPUT
{
int
fd
;
int
len
;
uint8_t
block
[
READ_BLOCKSIZE
];
uint8_t
*
inPtr
;
int
bytesRead
;
int
left
;
void
*
inflate_state
;
}
*
in
;
typedef
struct
{
uint8_t
byte
[
WRITE_BLOCKSIZE
];
}
outBlock
;
struct
OUTPUT
{
lua_State
*
L
;
lu_int32
flash_sig
;
int
len
;
outBlock
*
block
[
WRITE_BLOCKS
];
outBlock
buffer
;
int
ndx
;
uint32_t
crc
;
int
(
*
fullBlkCB
)
(
void
);
int
flashLen
;
int
flagsLen
;
int
flagsNdx
;
uint32_t
*
flags
;
const
char
*
error
;
}
*
out
;
#ifdef CONFIG_LUA_EMBEDDED_FLASH_STORE
extern
const
char
lua_flash_store_reserved
[
0
];
#endif
#ifdef NODE_DEBUG
extern
void
printf
(
const
char
*
fmt
,
...)
__attribute__
((
format
(
printf
,
1
,
2
)));
void
dumpStrt
(
stringtable
*
tb
,
const
char
*
type
)
{
int
i
,
j
;
GCObject
*
o
;
NODE_DBG
(
"
\n
Dumping %s String table
\n\n
========================
\n
"
,
type
);
NODE_DBG
(
"No of elements: %d
\n
Size of table: %d
\n
"
,
tb
->
nuse
,
tb
->
size
);
for
(
i
=
0
;
i
<
tb
->
size
;
i
++
)
for
(
o
=
tb
->
hash
[
i
],
j
=
0
;
o
;
(
o
=
o
->
gch
.
next
),
j
++
)
{
TString
*
ts
=
cast
(
TString
*
,
o
);
NODE_DBG
(
"%5d %5d %08x %08x %5d %1s %s
\n
"
,
i
,
j
,
(
size_t
)
ts
,
ts
->
tsv
.
hash
,
ts
->
tsv
.
len
,
ts_isreadonly
(
ts
)
?
"R"
:
" "
,
getstr
(
ts
));
}
}
LUA_API
void
dumpStrings
(
lua_State
*
L
)
{
dumpStrt
(
&
G
(
L
)
->
strt
,
"RAM"
);
if
(
G
(
L
)
->
ROstrt
.
hash
)
dumpStrt
(
&
G
(
L
)
->
ROstrt
,
"ROM"
);
}
#endif
#ifndef CONFIG_LUA_EMBEDDED_FLASH_STORE
/* =====================================================================================
* The next 4 functions: flashPosition, flashSetPosition, flashBlock and flashErase
* wrap writing to flash. The last two are platform dependent. Also note that any
* writes are suppressed if the global writeToFlash is false. This is used in
* phase I where the pass is used to size the structures in flash.
*/
static
void
flashSetPosition
(
uint32_t
offset
){
NODE_DBG
(
"flashSetPosition(%04x)
\n
"
,
offset
);
curOffset
=
offset
;
}
static
void
flashBlock
(
const
void
*
b
,
size_t
size
)
{
NODE_DBG
(
"flashBlock((%04x),%08x,%04x)
\n
"
,
curOffset
,(
unsigned
int
)
b
,
size
);
lua_assert
(
ALIGN_BITS
(
b
)
==
0
&&
ALIGN_BITS
(
size
)
==
0
);
platform_flash_write
(
b
,
flashAddrPhys
+
curOffset
,
size
);
curOffset
+=
size
;
}
static
void
flashErase
(
uint32_t
start
,
uint32_t
end
){
int
i
;
if
(
start
==
-
1
)
start
=
FLASH_PAGES
-
1
;
if
(
end
==
-
1
)
end
=
FLASH_PAGES
-
1
;
NODE_DBG
(
"flashErase(%04x,%04x)
\n
"
,
flashSector
+
start
,
flashSector
+
end
);
for
(
i
=
start
;
i
<=
end
;
i
++
)
platform_flash_erase_sector
(
flashSector
+
i
);
}
static
int
loadLFS
(
lua_State
*
L
);
static
int
loadLFSgc
(
lua_State
*
L
);
static
int
procFirstPass
(
void
);
#endif
/* =====================================================================================
* luaN_init(), luaN_reload_reboot() and luaN_index() are exported via lflash.h.
* The first is the startup hook used in lstate.c and the last two are
* implementations of the node.flash API calls.
*/
/*
* Hook in lstate.c:f_luaopen() to set up ROstrt and ROpvmain if needed
*/
LUAI_FUNC
void
luaN_init
(
lua_State
*
L
)
{
#ifdef CONFIG_LUA_EMBEDDED_FLASH_STORE
flashSize
=
CONFIG_LUA_EMBEDDED_FLASH_STORE
;
flashAddr
=
lua_flash_store_reserved
;
flashAddrPhys
=
spi_flash_cache2phys
(
lua_flash_store_reserved
);
if
(
flashAddrPhys
==
SPI_FLASH_CACHE2PHYS_FAIL
)
{
NODE_ERR
(
"spi_flash_cache2phys failed
\n
"
);
return
;
}
#else
const
esp_partition_t
*
part
=
esp_partition_find_first
(
PLATFORM_PARTITION_TYPE_NODEMCU
,
PLATFORM_PARTITION_SUBTYPE_NODEMCU_LFS
,
NULL
);
if
(
!
part
)
return
;
// Nothing to do if the size is zero
flashSize
=
part
->
size
;
// in bytes
flashAddrPhys
=
part
->
address
;
flashAddr
=
spi_flash_phys2cache
(
flashAddrPhys
,
SPI_FLASH_MMAP_DATA
);
if
(
!
flashAddr
)
{
spi_flash_mmap_handle_t
ignored
;
esp_err_t
err
=
spi_flash_mmap
(
flashAddrPhys
,
flashSize
,
SPI_FLASH_MMAP_DATA
,
cast
(
const
void
**
,
&
flashAddr
),
&
ignored
);
if
(
err
!=
ESP_OK
)
{
NODE_ERR
(
"Unable to access LFS partition - is it 64kB aligned as it needs to be?
\n
"
);
return
;
}
}
#endif
G
(
L
)
->
LFSsize
=
flashSize
;
flashSector
=
platform_flash_get_sector_of_address
(
flashAddrPhys
);
FlashHeader
*
fh
=
cast
(
FlashHeader
*
,
flashAddr
);
curOffset
=
0
;
/*
* For the LFS to be valid, its signature has to be correct for this build
* variant, the ROhash and main proto fields must be defined and the main proto
* address be within the LFS address bounds. (This last check is primarily to
* detect the direct imaging of an absolute LFS with the wrong base address.
*/
if
(
fh
->
flash_sig
==
0
||
fh
->
flash_sig
==
~
0
)
{
NODE_ERR
(
"No LFS image loaded
\n
"
);
return
;
}
if
((
fh
->
flash_sig
&
(
~
FLASH_SIG_ABSOLUTE
))
!=
FLASH_SIG
)
{
NODE_ERR
(
"Flash sig not correct: %u vs %u
\n
"
,
fh
->
flash_sig
&
(
~
FLASH_SIG_ABSOLUTE
),
FLASH_SIG
);
return
;
}
if
(
fh
->
pROhash
==
ALL_SET
||
((
fh
->
mainProto
-
cast
(
FlashAddr
,
fh
))
>=
fh
->
flash_size
))
{
NODE_ERR
(
"Flash size check failed: %x vs 0xFFFFFFFF; size: %u
\n
"
,
fh
->
mainProto
-
cast
(
FlashAddr
,
fh
),
fh
->
flash_size
);
return
;
}
G
(
L
)
->
ROstrt
.
hash
=
cast
(
GCObject
**
,
fh
->
pROhash
);
G
(
L
)
->
ROstrt
.
nuse
=
fh
->
nROuse
;
G
(
L
)
->
ROstrt
.
size
=
fh
->
nROsize
;
G
(
L
)
->
ROpvmain
=
cast
(
Proto
*
,
fh
->
mainProto
);
}
/*
* Library function called by node.flashreload(filename).
*/
LUALIB_API
int
luaN_reload_reboot
(
lua_State
*
L
)
{
#ifdef CONFIG_LUA_EMBEDDED_FLASH_STORE
// Updating the LFS section is disabled for now because any changes to the
// image requires updating its checksum to prevent boot failure.
lua_pushstring
(
L
,
"Not allowed to write to LFS section"
);
return
1
;
#else
// luaL_dbgbreak();
const
char
*
fn
=
lua_tostring
(
L
,
1
),
*
msg
=
""
;
int
status
;
if
(
G
(
L
)
->
LFSsize
==
0
)
{
lua_pushstring
(
L
,
"No LFS partition allocated"
);
return
1
;
}
/*
* Do a protected call of loadLFS.
*
* - This will normally rewrite the LFS and reboot, with no return.
* - If an error occurs then it is sent to the UART.
* - If this occured in the 1st pass, the previous LFS is unchanged so it is
* safe to return to the calling Lua.
* - If in the 1st pass, then the ESP is rebooted.
*/
status
=
lua_cpcall
(
L
,
&
loadLFS
,
cast
(
void
*
,
fn
));
if
(
!
out
||
out
->
fullBlkCB
==
procFirstPass
)
{
/*
* Never entered the 2nd pass, so it is safe to return the error. Note
* that I've gone to some trouble to ensure that all dynamically allocated
* working areas have been freed, so that we have no memory leaks.
*/
if
(
status
==
LUA_ERRMEM
)
msg
=
"Memory allocation error"
;
else
if
(
out
&&
out
->
error
)
msg
=
out
->
error
;
else
msg
=
"Unknown Error"
;
/* We can clean up and return error */
lua_cpcall
(
L
,
&
loadLFSgc
,
NULL
);
lua_settop
(
L
,
0
);
lua_pushstring
(
L
,
msg
);
return
1
;
}
if
(
status
==
0
)
{
/* Successful LFS rewrite */
msg
=
"LFS region updated. Restarting."
;
}
else
{
/* We have errored during the second pass so clear the LFS and reboot */
if
(
status
==
LUA_ERRMEM
)
msg
=
"Memory allocation error"
;
else
if
(
out
->
error
)
msg
=
out
->
error
;
else
msg
=
"Unknown Error"
;
flashErase
(
0
,
-
1
);
}
NODE_ERR
(
"%s
\n
"
,
msg
);
esp_restart
();
return
0
;
#endif // CONFIG_LUA_EMBEDDED_FLASH_STORE
}
/*
* If the arg is a valid LFS module name then return the LClosure
* pointing to it. Otherwise return:
* - The Unix time that the LFS was built
* - The base address and length of the LFS
* - An array of the module names in the LFS
*/
LUAI_FUNC
int
luaN_index
(
lua_State
*
L
)
{
int
n
=
lua_gettop
(
L
);
/* Return nil + the LFS base address if the LFS size > 0 and it isn't loaded */
if
(
!
(
G
(
L
)
->
ROpvmain
))
{
lua_settop
(
L
,
0
);
lua_pushnil
(
L
);
if
(
G
(
L
)
->
LFSsize
)
{
lua_pushinteger
(
L
,
(
lua_Integer
)
flashAddr
);
lua_pushinteger
(
L
,
flashAddrPhys
);
lua_pushinteger
(
L
,
G
(
L
)
->
LFSsize
);
return
4
;
}
else
{
return
1
;
}
}
/* Push the LClosure of the LFS index function */
Closure
*
cl
=
luaF_newLclosure
(
L
,
0
,
hvalue
(
gt
(
L
)));
cl
->
l
.
p
=
G
(
L
)
->
ROpvmain
;
lua_settop
(
L
,
n
+
1
);
setclvalue
(
L
,
L
->
top
-
1
,
cl
);
/* Move it infront of the arguments and call the index function */
lua_insert
(
L
,
1
);
lua_call
(
L
,
n
,
LUA_MULTRET
);
/* Return it if the response if a single value (the function) */
if
(
lua_gettop
(
L
)
==
1
)
return
1
;
lua_assert
(
lua_gettop
(
L
)
==
2
);
/* Otherwise add the base address of the LFS, and its size bewteen the */
/* Unix time and the module list, then return all 4 params. */
lua_pushinteger
(
L
,
(
lua_Integer
)
flashAddr
);
lua_insert
(
L
,
2
);
lua_pushinteger
(
L
,
flashAddrPhys
);
lua_insert
(
L
,
3
);
lua_pushinteger
(
L
,
cast
(
FlashHeader
*
,
flashAddr
)
->
flash_size
);
lua_insert
(
L
,
4
);
return
5
;
}
#ifndef CONFIG_LUA_EMBEDDED_FLASH_STORE
/* =====================================================================================
* The following routines use my uzlib which was based on pfalcon's inflate and
* deflate routines. The standard NodeMCU make also makes two host tools uz_zip
* and uz_unzip which also use these and luac.cross uses the deflate. As discussed
* below, The main action routine loadLFS() calls uzlib_inflate() to do the actual
* stream inflation but uses three supplied CBs to abstract input and output
* stream handling.
*
* ESP8266 RAM limitations and heap fragmentation are a key implementation
* constraint and hence these routines use a number of ~2K buffers (11) as
* working storage.
*
* The inflate is done twice, in order to limit storage use and avoid forward /
* backward reference issues. However this has a major advantage that the LFS
* is scanned with the headers, CRC, etc. validated BEFORE the write to flash
* is started, so the only real chance of failure during the second pass
* write is if a power fail occurs during the pass.
*/
static
void
flash_error
(
const
char
*
err
)
{
if
(
out
)
out
->
error
=
err
;
if
(
in
&&
in
->
inflate_state
)
uz_free
(
in
->
inflate_state
);
lua_pushnil
(
out
->
L
);
/* can't use it on a cpcall anyway */
lua_error
(
out
->
L
);
}
/*
* uzlib_inflate does a stream inflate on an RFC 1951 encoded data stream.
* It uses three application-specific CBs passed in the call to do the work:
*
* - get_byte() CB to return next byte in input stream
* - put_byte() CB to output byte to output buffer
* - recall_byte() CB to output byte to retrieve a historic byte from
* the output buffer.
*
* Note that put_byte() also triggers secondary CBs to do further processing.
*/
static
uint8_t
get_byte
(
void
)
{
if
(
--
in
->
left
<
0
)
{
/* Read next input block */
int
remaining
=
in
->
len
-
in
->
bytesRead
;
int
wanted
=
remaining
>=
READ_BLOCKSIZE
?
READ_BLOCKSIZE
:
remaining
;
if
(
vfs_read
(
in
->
fd
,
in
->
block
,
wanted
)
!=
wanted
)
flash_error
(
"read error on LFS image file"
);
platform_wdt_feed
();
in
->
bytesRead
+=
wanted
;
in
->
inPtr
=
in
->
block
;
in
->
left
=
wanted
-
1
;
}
return
*
in
->
inPtr
++
;
}
static
void
put_byte
(
uint8_t
value
)
{
int
offset
=
out
->
ndx
%
WRITE_BLOCKSIZE
;
/* counts from 0 */
out
->
block
[
0
]
->
byte
[
offset
++
]
=
value
;
out
->
ndx
++
;
if
(
offset
==
WRITE_BLOCKSIZE
||
out
->
ndx
==
out
->
len
)
{
if
(
out
->
fullBlkCB
)
out
->
fullBlkCB
();
/* circular shift the block pointers (redundant on last block, but so what) */
outBlock
*
nextBlock
=
out
->
block
[
WRITE_BLOCKS
-
1
];
memmove
(
out
->
block
+
1
,
out
->
block
,
(
WRITE_BLOCKS
-
1
)
*
sizeof
(
void
*
));
out
->
block
[
0
]
=
nextBlock
;
}
}
static
uint8_t
recall_byte
(
uint
offset
)
{
if
(
offset
>
DICTIONARY_WINDOW
||
offset
>=
out
->
ndx
)
flash_error
(
"invalid dictionary offset on inflate"
);
/* ndx starts at 1. Need relative to 0 */
uint
n
=
out
->
ndx
-
offset
;
uint
pos
=
n
%
WRITE_BLOCKSIZE
;
uint
blockNo
=
out
->
ndx
/
WRITE_BLOCKSIZE
-
n
/
WRITE_BLOCKSIZE
;
return
out
->
block
[
blockNo
]
->
byte
[
pos
];
}
/*
* On the first pass the break index is set to call this process at the end
* of each completed output buffer.
* - On the first call, the Flash Header is checked.
* - On each call the CRC is rolled up for that buffer.
* - Once the flags array is in-buffer this is also captured.
* This logic is slightly complicated by the last buffer is typically short.
*/
int
procFirstPass
(
void
)
{
int
len
=
(
out
->
ndx
%
WRITE_BLOCKSIZE
)
?
out
->
ndx
%
WRITE_BLOCKSIZE
:
WRITE_BLOCKSIZE
;
if
(
out
->
ndx
<=
WRITE_BLOCKSIZE
)
{
/* Process the flash header and cache the FlashHeader fields we need */
FlashHeader
*
fh
=
cast
(
FlashHeader
*
,
out
->
block
[
0
]);
out
->
flashLen
=
fh
->
flash_size
;
/* in bytes */
out
->
flagsLen
=
(
out
->
len
-
fh
->
flash_size
)
/
WORDSIZE
;
/* in words */
out
->
flash_sig
=
fh
->
flash_sig
;
if
((
fh
->
flash_sig
&
FLASH_FORMAT_MASK
)
!=
FLASH_FORMAT_VERSION
)
flash_error
(
"Incorrect LFS header version"
);
if
((
fh
->
flash_sig
&
FLASH_SIG_B2_MASK
)
!=
FLASH_SIG_B2
)
flash_error
(
"Incorrect LFS build type"
);
if
((
fh
->
flash_sig
&
~
FLASH_SIG_ABSOLUTE
)
!=
FLASH_SIG
)
flash_error
(
"incorrect LFS header signature"
);
if
(
fh
->
flash_size
>
flashSize
)
flash_error
(
"LFS Image too big for configured LFS region"
);
if
((
fh
->
flash_size
&
0x3
)
||
fh
->
flash_size
>
flashSize
||
out
->
flagsLen
!=
1
+
(
out
->
flashLen
/
WORDSIZE
-
1
)
/
BITS_PER_WORD
)
flash_error
(
"LFS length mismatch"
);
out
->
flags
=
luaM_newvector
(
out
->
L
,
out
->
flagsLen
,
uint
);
}
/* update running CRC */
out
->
crc
=
uzlib_crc32
(
out
->
block
[
0
],
len
,
out
->
crc
);
/* copy out any flag vector */
if
(
out
->
ndx
>
out
->
flashLen
)
{
int
start
=
out
->
flashLen
-
(
out
->
ndx
-
len
);
if
(
start
<
0
)
start
=
0
;
memcpy
(
out
->
flags
+
out
->
flagsNdx
,
out
->
block
[
0
]
->
byte
+
start
,
len
-
start
);
out
->
flagsNdx
+=
(
len
-
start
)
/
WORDSIZE
;
/* flashLen and len are word aligned */
}
return
1
;
}
int
procSecondPass
(
void
)
{
/*
* The length rules are different for the second pass since this only processes
* upto the flashLen and not the full image. This also works in word units.
* (We've already validated these are word multiples.)
*/
int
i
,
len
=
(
out
->
ndx
>
out
->
flashLen
)
?
(
out
->
flashLen
%
WRITE_BLOCKSIZE
)
/
WORDSIZE
:
WRITE_BLOCKSIZE
/
WORDSIZE
;
uint32_t
*
buf
=
(
uint32_t
*
)
out
->
buffer
.
byte
;
uint32_t
flags
=
0
;
/*
* Relocate all the addresses tagged in out->flags. This can't be done in
* place because the out->blocks are still in use as dictionary content so
* first copy the block to a working buffer and do the relocation in this.
*/
memcpy
(
out
->
buffer
.
byte
,
out
->
block
[
0
]
->
byte
,
WRITE_BLOCKSIZE
);
for
(
i
=
0
;
i
<
len
;
i
++
,
flags
>>=
1
)
{
if
((
i
&
31
)
==
0
)
flags
=
out
->
flags
[
out
->
flagsNdx
++
];
if
(
flags
&
1
)
buf
[
i
]
=
WORDSIZE
*
buf
[
i
]
+
cast
(
uint32_t
,
flashAddr
);
// mapped, not phys
}
/*
* On first block, set the flash_sig has the in progress bit set and this
* is not cleared until end.
*/
if
(
out
->
ndx
<=
WRITE_BLOCKSIZE
)
buf
[
0
]
=
out
->
flash_sig
|
FLASH_SIG_IN_PROGRESS
;
flashBlock
(
buf
,
len
*
WORDSIZE
);
if
(
out
->
ndx
>=
out
->
flashLen
)
{
/* we're done so disable CB and rewrite flash sig to complete flash */
flashSetPosition
(
0
);
flashBlock
(
&
out
->
flash_sig
,
WORDSIZE
);
out
->
fullBlkCB
=
NULL
;
}
return
1
;
}
/*
* loadLFS)() is protected called from luaN_reload_reboot so that it can recover
* from out of memory and other thrown errors. loadLFSgc() GCs any resources.
*/
static
int
loadLFS
(
lua_State
*
L
)
{
const
char
*
fn
=
cast
(
const
char
*
,
lua_touserdata
(
L
,
1
));
int
i
,
res
;
uint32_t
crc
;
/* Allocate and zero in and out structures */
in
=
NULL
;
out
=
NULL
;
in
=
luaM_new
(
L
,
struct
INPUT
);
memset
(
in
,
0
,
sizeof
(
*
in
));
out
=
luaM_new
(
L
,
struct
OUTPUT
);
memset
(
out
,
0
,
sizeof
(
*
out
));
out
->
L
=
L
;
out
->
fullBlkCB
=
procFirstPass
;
out
->
crc
=
~
0
;
/* Open LFS image/ file, read unpacked length from last 4 byte and rewind */
if
(
!
(
in
->
fd
=
vfs_open
(
fn
,
"r"
)))
flash_error
(
"LFS image file not found"
);
in
->
len
=
vfs_size
(
in
->
fd
);
if
(
in
->
len
<=
200
||
/* size of an empty luac output */
vfs_lseek
(
in
->
fd
,
in
->
len
-
4
,
VFS_SEEK_SET
)
!=
in
->
len
-
4
||
vfs_read
(
in
->
fd
,
&
out
->
len
,
sizeof
(
uint
))
!=
sizeof
(
uint
))
flash_error
(
"read error on LFS image file"
);
vfs_lseek
(
in
->
fd
,
0
,
VFS_SEEK_SET
);
/* Allocate the out buffers */
for
(
i
=
0
;
i
<
WRITE_BLOCKS
;
i
++
)
out
->
block
[
i
]
=
luaM_new
(
L
,
outBlock
);
/* first inflate pass */
if
(
uzlib_inflate
(
get_byte
,
put_byte
,
recall_byte
,
in
->
len
,
&
crc
,
&
in
->
inflate_state
)
<
0
)
flash_error
(
"read error on LFS image file"
);
if
(
crc
!=
~
out
->
crc
)
flash_error
(
"checksum error on LFS image file"
);
out
->
fullBlkCB
=
procSecondPass
;
out
->
flagsNdx
=
0
;
out
->
ndx
=
0
;
in
->
bytesRead
=
in
->
left
=
0
;
/*
* Once we have completed the 1st pass then the LFS image has passed the
* basic signature, crc and length checks, so now we can reset the counts
* to do the actual write to flash on the second pass.
*/
vfs_lseek
(
in
->
fd
,
0
,
VFS_SEEK_SET
);
flashErase
(
0
,(
out
->
flashLen
-
1
)
/
FLASH_PAGE_SIZE
);
flashSetPosition
(
0
);
res
=
uzlib_inflate
(
get_byte
,
put_byte
,
recall_byte
,
in
->
len
,
&
crc
,
&
in
->
inflate_state
);
if
(
res
<
0
)
{
// UZLIB_OK == 0, UZLIB_DONE == 1
const
char
*
err
[]
=
{
"Data_error during decompression"
,
"Chksum_error during decompression"
,
"Dictionary error during decompression"
,
"Memory_error during decompression"
};
flash_error
(
err
[
UZLIB_DATA_ERROR
-
res
]);
}
return
0
;
}
static
int
loadLFSgc
(
lua_State
*
L
)
{
int
i
;
if
(
out
)
{
for
(
i
=
0
;
i
<
WRITE_BLOCKS
;
i
++
)
if
(
out
->
block
[
i
])
luaM_free
(
L
,
out
->
block
[
i
]);
if
(
out
->
flags
)
luaM_freearray
(
L
,
out
->
flags
,
out
->
flagsLen
,
uint32_t
);
luaM_free
(
L
,
out
);
}
if
(
in
)
{
if
(
in
->
fd
)
vfs_close
(
in
->
fd
);
luaM_free
(
L
,
in
);
}
return
0
;
}
#endif
components/lua/lflash.h
0 → 100644
View file @
eaac369d
/*
** lflashe.h
** See Copyright Notice in lua.h
*/
#ifndef lflash_h
#define lflash_h
#include "lobject.h"
#include "lstate.h"
#include "lzio.h"
#ifdef LUA_NUMBER_INTEGRAL
# define FLASH_SIG_B1 0x02
#else
# define FLASH_SIG_B1 0x00
#endif
#define FLASH_FORMAT_VERSION (1 << 8)
#define FLASH_FORMAT_MASK 0xF00
#ifdef LUA_PACK_TVALUES
#ifdef LUA_NUMBER_INTEGRAL
#error "LUA_PACK_TVALUES is only valid for Floating point builds"
#endif
# define FLASH_SIG_B2 0x04
#else
# define FLASH_SIG_B2 0x00
#endif
# define FLASH_SIG_B2_MASK 0x04
#define FLASH_SIG_ABSOLUTE 0x01
#define FLASH_SIG_IN_PROGRESS 0x08
#define FLASH_SIG (0xfafaa050 | FLASH_FORMAT_VERSION |FLASH_SIG_B2 | FLASH_SIG_B1)
typedef
lu_int32
FlashAddr
;
typedef
struct
{
lu_int32
flash_sig
;
/* a stabdard fingerprint identifying an LFS image */
lu_int32
flash_size
;
/* Size of LFS image */
FlashAddr
mainProto
;
/* address of main Proto in Proto hierarchy */
FlashAddr
pROhash
;
/* address of ROstrt hash */
lu_int32
nROuse
;
/* number of elements in ROstrt */
int
nROsize
;
/* size of ROstrt */
lu_int32
fill1
;
/* reserved */
lu_int32
fill2
;
/* reserved */
}
FlashHeader
;
LUAI_FUNC
void
luaN_init
(
lua_State
*
L
);
LUAI_FUNC
int
luaN_flashSetup
(
lua_State
*
L
);
LUAI_FUNC
int
luaN_reload_reboot
(
lua_State
*
L
);
LUAI_FUNC
int
luaN_index
(
lua_State
*
L
);
#endif
components/lua/lfunc.c
View file @
eaac369d
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
#define LUAC_CROSS_FILE
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lua.h"
#include
C_HEADER_STRING
#include
<string.h>
#include "lfunc.h"
#include "lfunc.h"
#include "lgc.h"
#include "lgc.h"
...
@@ -146,7 +146,7 @@ void luaF_freeproto (lua_State *L, Proto *f) {
...
@@ -146,7 +146,7 @@ void luaF_freeproto (lua_State *L, Proto *f) {
luaM_freearray
(
L
,
f
->
k
,
f
->
sizek
,
TValue
);
luaM_freearray
(
L
,
f
->
k
,
f
->
sizek
,
TValue
);
luaM_freearray
(
L
,
f
->
locvars
,
f
->
sizelocvars
,
struct
LocVar
);
luaM_freearray
(
L
,
f
->
locvars
,
f
->
sizelocvars
,
struct
LocVar
);
luaM_freearray
(
L
,
f
->
upvalues
,
f
->
sizeupvalues
,
TString
*
);
luaM_freearray
(
L
,
f
->
upvalues
,
f
->
sizeupvalues
,
TString
*
);
if
(
!
proto_is
_
readonly
(
f
))
{
if
(
!
proto_isreadonly
(
f
))
{
luaM_freearray
(
L
,
f
->
code
,
f
->
sizecode
,
Instruction
);
luaM_freearray
(
L
,
f
->
code
,
f
->
sizecode
,
Instruction
);
#ifdef LUA_OPTIMIZE_DEBUG
#ifdef LUA_OPTIMIZE_DEBUG
if
(
f
->
packedlineinfo
)
{
if
(
f
->
packedlineinfo
)
{
...
...
components/lua/lfunc.h
View file @
eaac369d
...
@@ -18,9 +18,6 @@
...
@@ -18,9 +18,6 @@
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
cast(int, sizeof(TValue *)*((n)-1)))
cast(int, sizeof(TValue *)*((n)-1)))
#define proto_readonly(p) l_setbit((p)->marked, READONLYBIT)
#define proto_is_readonly(p) testbit((p)->marked, READONLYBIT)
LUAI_FUNC
Proto
*
luaF_newproto
(
lua_State
*
L
);
LUAI_FUNC
Proto
*
luaF_newproto
(
lua_State
*
L
);
LUAI_FUNC
Closure
*
luaF_newCclosure
(
lua_State
*
L
,
int
nelems
,
Table
*
e
);
LUAI_FUNC
Closure
*
luaF_newCclosure
(
lua_State
*
L
,
int
nelems
,
Table
*
e
);
LUAI_FUNC
Closure
*
luaF_newLclosure
(
lua_State
*
L
,
int
nelems
,
Table
*
e
);
LUAI_FUNC
Closure
*
luaF_newLclosure
(
lua_State
*
L
,
int
nelems
,
Table
*
e
);
...
...
components/lua/lgc.c
View file @
eaac369d
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
#define LUAC_CROSS_FILE
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lua.h"
#include
C_HEADER_STRING
#include
<string.h>
#include "ldebug.h"
#include "ldebug.h"
#include "ldo.h"
#include "ldo.h"
...
@@ -37,10 +37,10 @@
...
@@ -37,10 +37,10 @@
#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)
#define stringmark(s)
if (!isLFSobject(&(s)->tsv)) {
reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)
;}
#define isfinalized(u) testbit(
(u)->
marked, FINALIZEDBIT)
#define isfinalized(u) testbit(
get
marked
(u)
, FINALIZEDBIT)
#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT)
#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT)
...
@@ -61,15 +61,21 @@
...
@@ -61,15 +61,21 @@
static
void
removeentry
(
Node
*
n
)
{
static
void
removeentry
(
Node
*
n
)
{
lua_assert
(
ttisnil
(
gval
(
n
)));
lua_assert
(
ttisnil
(
gval
(
n
)));
if
(
iscollectable
(
gkey
(
n
)))
if
(
ttype
(
gkey
(
n
))
!=
LUA_TDEADKEY
&&
iscollectable
(
gkey
(
n
)))
// The gkey is always in RAM so it can be marked as DEAD even though it
// refers to an LFS object.
setttype
(
gkey
(
n
),
LUA_TDEADKEY
);
/* dead key; remove it */
setttype
(
gkey
(
n
),
LUA_TDEADKEY
);
/* dead key; remove it */
}
}
static
void
reallymarkobject
(
global_State
*
g
,
GCObject
*
o
)
{
static
void
reallymarkobject
(
global_State
*
g
,
GCObject
*
o
)
{
/* don't mark LFS Protos (or strings) */
if
(
gettt
(
&
o
->
gch
)
==
LUA_TPROTO
&&
isLFSobject
(
&
(
o
->
gch
)))
return
;
lua_assert
(
iswhite
(
o
)
&&
!
isdead
(
g
,
o
));
lua_assert
(
iswhite
(
o
)
&&
!
isdead
(
g
,
o
));
white2gray
(
o
);
white2gray
(
o
);
switch
(
o
->
gch
.
tt
)
{
switch
(
gettt
(
&
o
->
gch
)
)
{
case
LUA_TSTRING
:
{
case
LUA_TSTRING
:
{
return
;
return
;
}
}
...
@@ -159,10 +165,14 @@ static int traversetable (global_State *g, Table *h) {
...
@@ -159,10 +165,14 @@ static int traversetable (global_State *g, Table *h) {
int
i
;
int
i
;
int
weakkey
=
0
;
int
weakkey
=
0
;
int
weakvalue
=
0
;
int
weakvalue
=
0
;
const
TValue
*
mode
;
const
TValue
*
mode
=
luaO_nilobject
;
if
(
h
->
metatable
&&
!
luaR_isrotable
(
h
->
metatable
))
if
(
h
->
metatable
)
{
if
(
!
luaR_isrotable
(
h
->
metatable
))
markobject
(
g
,
h
->
metatable
);
markobject
(
g
,
h
->
metatable
);
mode
=
gfasttm
(
g
,
h
->
metatable
,
TM_MODE
);
mode
=
gfasttm
(
g
,
h
->
metatable
,
TM_MODE
);
}
if
(
mode
&&
ttisstring
(
mode
))
{
/* is there a weak mode? */
if
(
mode
&&
ttisstring
(
mode
))
{
/* is there a weak mode? */
weakkey
=
(
strchr
(
svalue
(
mode
),
'k'
)
!=
NULL
);
weakkey
=
(
strchr
(
svalue
(
mode
),
'k'
)
!=
NULL
);
weakvalue
=
(
strchr
(
svalue
(
mode
),
'v'
)
!=
NULL
);
weakvalue
=
(
strchr
(
svalue
(
mode
),
'v'
)
!=
NULL
);
...
@@ -180,6 +190,8 @@ static int traversetable (global_State *g, Table *h) {
...
@@ -180,6 +190,8 @@ static int traversetable (global_State *g, Table *h) {
while
(
i
--
)
while
(
i
--
)
markvalue
(
g
,
&
h
->
array
[
i
]);
markvalue
(
g
,
&
h
->
array
[
i
]);
}
}
if
(
luaH_isdummy
(
h
->
node
))
return
weakkey
||
weakvalue
;
i
=
sizenode
(
h
);
i
=
sizenode
(
h
);
while
(
i
--
)
{
while
(
i
--
)
{
Node
*
n
=
gnode
(
h
,
i
);
Node
*
n
=
gnode
(
h
,
i
);
...
@@ -202,6 +214,8 @@ static int traversetable (global_State *g, Table *h) {
...
@@ -202,6 +214,8 @@ static int traversetable (global_State *g, Table *h) {
*/
*/
static
void
traverseproto
(
global_State
*
g
,
Proto
*
f
)
{
static
void
traverseproto
(
global_State
*
g
,
Proto
*
f
)
{
int
i
;
int
i
;
if
(
isLFSobject
(
f
))
return
;
/* don't traverse Protos in LFS */
if
(
f
->
source
)
stringmark
(
f
->
source
);
if
(
f
->
source
)
stringmark
(
f
->
source
);
for
(
i
=
0
;
i
<
f
->
sizek
;
i
++
)
/* mark literals */
for
(
i
=
0
;
i
<
f
->
sizek
;
i
++
)
/* mark literals */
markvalue
(
g
,
&
f
->
k
[
i
]);
markvalue
(
g
,
&
f
->
k
[
i
]);
...
@@ -282,7 +296,7 @@ static l_mem propagatemark (global_State *g) {
...
@@ -282,7 +296,7 @@ static l_mem propagatemark (global_State *g) {
GCObject
*
o
=
g
->
gray
;
GCObject
*
o
=
g
->
gray
;
lua_assert
(
isgray
(
o
));
lua_assert
(
isgray
(
o
));
gray2black
(
o
);
gray2black
(
o
);
switch
(
o
->
gch
.
tt
)
{
switch
(
gettt
(
&
o
->
gch
)
)
{
case
LUA_TTABLE
:
{
case
LUA_TTABLE
:
{
Table
*
h
=
gco2h
(
o
);
Table
*
h
=
gco2h
(
o
);
g
->
gray
=
h
->
gclist
;
g
->
gray
=
h
->
gclist
;
...
@@ -317,7 +331,7 @@ static l_mem propagatemark (global_State *g) {
...
@@ -317,7 +331,7 @@ static l_mem propagatemark (global_State *g) {
sizeof
(
TValue
)
*
p
->
sizek
+
sizeof
(
TValue
)
*
p
->
sizek
+
sizeof
(
LocVar
)
*
p
->
sizelocvars
+
sizeof
(
LocVar
)
*
p
->
sizelocvars
+
sizeof
(
TString
*
)
*
p
->
sizeupvalues
+
sizeof
(
TString
*
)
*
p
->
sizeupvalues
+
(
proto_is
_
readonly
(
p
)
?
0
:
sizeof
(
Instruction
)
*
p
->
sizecode
+
(
proto_isreadonly
(
p
)
?
0
:
sizeof
(
Instruction
)
*
p
->
sizecode
+
#ifdef LUA_OPTIMIZE_DEBUG
#ifdef LUA_OPTIMIZE_DEBUG
(
p
->
packedlineinfo
?
(
p
->
packedlineinfo
?
strlen
(
cast
(
char
*
,
p
->
packedlineinfo
))
+
1
:
strlen
(
cast
(
char
*
,
p
->
packedlineinfo
))
+
1
:
...
@@ -387,8 +401,11 @@ static void cleartable (GCObject *l) {
...
@@ -387,8 +401,11 @@ static void cleartable (GCObject *l) {
static
void
freeobj
(
lua_State
*
L
,
GCObject
*
o
)
{
static
void
freeobj
(
lua_State
*
L
,
GCObject
*
o
)
{
switch
(
o
->
gch
.
tt
)
{
switch
(
gettt
(
&
o
->
gch
))
{
case
LUA_TPROTO
:
luaF_freeproto
(
L
,
gco2p
(
o
));
break
;
case
LUA_TPROTO
:
lua_assert
(
!
isLFSobject
(
&
(
o
->
gch
)));
luaF_freeproto
(
L
,
gco2p
(
o
));
break
;
case
LUA_TFUNCTION
:
luaF_freeclosure
(
L
,
gco2cl
(
o
));
break
;
case
LUA_TFUNCTION
:
luaF_freeclosure
(
L
,
gco2cl
(
o
));
break
;
case
LUA_TUPVAL
:
luaF_freeupval
(
L
,
gco2uv
(
o
));
break
;
case
LUA_TUPVAL
:
luaF_freeupval
(
L
,
gco2uv
(
o
));
break
;
case
LUA_TTABLE
:
luaH_free
(
L
,
gco2h
(
o
));
break
;
case
LUA_TTABLE
:
luaH_free
(
L
,
gco2h
(
o
));
break
;
...
@@ -398,6 +415,7 @@ static void freeobj (lua_State *L, GCObject *o) {
...
@@ -398,6 +415,7 @@ static void freeobj (lua_State *L, GCObject *o) {
break
;
break
;
}
}
case
LUA_TSTRING
:
{
case
LUA_TSTRING
:
{
lua_assert
(
!
isLFSobject
(
&
(
o
->
gch
)));
G
(
L
)
->
strt
.
nuse
--
;
G
(
L
)
->
strt
.
nuse
--
;
luaM_freemem
(
L
,
o
,
sizestring
(
gco2ts
(
o
)));
luaM_freemem
(
L
,
o
,
sizestring
(
gco2ts
(
o
)));
break
;
break
;
...
@@ -420,6 +438,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
...
@@ -420,6 +438,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
global_State
*
g
=
G
(
L
);
global_State
*
g
=
G
(
L
);
int
deadmask
=
otherwhite
(
g
);
int
deadmask
=
otherwhite
(
g
);
while
((
curr
=
*
p
)
!=
NULL
&&
count
--
>
0
)
{
while
((
curr
=
*
p
)
!=
NULL
&&
count
--
>
0
)
{
lua_assert
(
!
isLFSobject
(
&
(
curr
->
gch
))
||
curr
->
gch
.
tt
==
LUA_TTHREAD
);
if
(
curr
->
gch
.
tt
==
LUA_TTHREAD
)
/* sweep open upvalues of each thread */
if
(
curr
->
gch
.
tt
==
LUA_TTHREAD
)
/* sweep open upvalues of each thread */
sweepwholelist
(
L
,
&
gco2th
(
curr
)
->
openupval
);
sweepwholelist
(
L
,
&
gco2th
(
curr
)
->
openupval
);
if
((
curr
->
gch
.
marked
^
WHITEBITS
)
&
deadmask
)
{
/* not dead? */
if
((
curr
->
gch
.
marked
^
WHITEBITS
)
&
deadmask
)
{
/* not dead? */
...
@@ -538,7 +557,7 @@ static void atomic (lua_State *L) {
...
@@ -538,7 +557,7 @@ static void atomic (lua_State *L) {
size_t
udsize
;
/* total size of userdata to be finalized */
size_t
udsize
;
/* total size of userdata to be finalized */
/* remark occasional upvalues of (maybe) dead threads */
/* remark occasional upvalues of (maybe) dead threads */
remarkupvals
(
g
);
remarkupvals
(
g
);
/* traverse objects cau
t
ch by write barrier and by 'remarkupvals' */
/* traverse objects cauch
t
by write barrier and by 'remarkupvals' */
propagateall
(
g
);
propagateall
(
g
);
/* remark weak tables */
/* remark weak tables */
g
->
gray
=
g
->
weak
;
g
->
gray
=
g
->
weak
;
...
@@ -694,10 +713,10 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
...
@@ -694,10 +713,10 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
global_State
*
g
=
G
(
L
);
global_State
*
g
=
G
(
L
);
lua_assert
(
isblack
(
o
)
&&
iswhite
(
v
)
&&
!
isdead
(
g
,
v
)
&&
!
isdead
(
g
,
o
));
lua_assert
(
isblack
(
o
)
&&
iswhite
(
v
)
&&
!
isdead
(
g
,
v
)
&&
!
isdead
(
g
,
o
));
lua_assert
(
g
->
gcstate
!=
GCSfinalize
&&
g
->
gcstate
!=
GCSpause
);
lua_assert
(
g
->
gcstate
!=
GCSfinalize
&&
g
->
gcstate
!=
GCSpause
);
lua_assert
(
ttype
(
&
o
->
gch
)
!=
LUA_TTABLE
);
lua_assert
(
o
->
gch
.
tt
!=
LUA_TTABLE
);
/* must keep invariant? */
/* must keep invariant? */
if
(
g
->
gcstate
==
GCSpropagate
)
if
(
g
->
gcstate
==
GCSpropagate
)
reallymarkobject
(
g
,
v
);
/*
r
estore invariant */
reallymarkobject
(
g
,
v
);
/*
R
estore invariant */
else
/* don't mind */
else
/* don't mind */
makewhite
(
g
,
o
);
/* mark as white just to avoid other barriers */
makewhite
(
g
,
o
);
/* mark as white just to avoid other barriers */
}
}
...
...
components/lua/lgc.h
View file @
eaac369d
...
@@ -79,6 +79,7 @@
...
@@ -79,6 +79,7 @@
#define VALUEWEAKBIT 4
#define VALUEWEAKBIT 4
#define FIXEDBIT 5
#define FIXEDBIT 5
#define SFIXEDBIT 6
#define SFIXEDBIT 6
#define LFSBIT 6
#define READONLYBIT 7
#define READONLYBIT 7
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
...
@@ -100,6 +101,13 @@
...
@@ -100,6 +101,13 @@
#define isfixedstack(x) testbit((x)->marked, FIXEDSTACKBIT)
#define isfixedstack(x) testbit((x)->marked, FIXEDSTACKBIT)
#define fixedstack(x) l_setbit((x)->marked, FIXEDSTACKBIT)
#define fixedstack(x) l_setbit((x)->marked, FIXEDSTACKBIT)
#define unfixedstack(x) resetbit((x)->marked, FIXEDSTACKBIT)
#define unfixedstack(x) resetbit((x)->marked, FIXEDSTACKBIT)
#ifndef LUA_CROSS_COMPILER
#define isLFSobject(x) testbit(getmarked(x), LFSBIT)
#define stringfix(s) if (!test2bits(getmarked(&(s)->tsv), FIXEDBIT, LFSBIT)) {l_setbit((s)->tsv.marked, FIXEDBIT);}
#else
#define isLFSobject(x) (0)
#define stringfix(s) {l_setbit((s)->tsv.marked, FIXEDBIT);}
#endif
#define luaC_checkGC(L) { \
#define luaC_checkGC(L) { \
condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
...
...
components/lua/llex.c
View file @
eaac369d
...
@@ -10,9 +10,9 @@
...
@@ -10,9 +10,9 @@
#define LUAC_CROSS_FILE
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lua.h"
#include
C_HEADER_CTYPE
#include
<ctype.h>
#include
C_HEADER_LOCALE
#include
<locale.h>
#include
C_HEADER_STRING
#include
<string.h>
#include "ldo.h"
#include "ldo.h"
#include "llex.h"
#include "llex.h"
...
...
components/lua/lmathlib.c
View file @
eaac369d
...
@@ -10,8 +10,8 @@
...
@@ -10,8 +10,8 @@
#define LUAC_CROSS_FILE
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lua.h"
#include
C_HEADER_STDLIB
#include
<stdlib.h>
#include
C_HEADER_MATH
#include
<math.h>
#include "lauxlib.h"
#include "lauxlib.h"
#include "lualib.h"
#include "lualib.h"
...
@@ -309,92 +309,57 @@ static int math_randomseed (lua_State *L) {
...
@@ -309,92 +309,57 @@ static int math_randomseed (lua_State *L) {
return
0
;
return
0
;
}
}
LROT_PUBLIC_BEGIN
(
math
)
#undef MIN_OPT_LEVEL
#define MIN_OPT_LEVEL 1
#include "lrodefs.h"
const
LUA_REG_TYPE
math_map
[]
=
{
#ifdef LUA_NUMBER_INTEGRAL
#ifdef LUA_NUMBER_INTEGRAL
{
LSTRKEY
(
"abs"
),
LFUNCVAL
(
math_abs
)},
LROT_FUNCENTRY
(
abs
,
math_abs
)
{
LSTRKEY
(
"ceil"
),
LFUNCVAL
(
math_identity
)},
LROT_FUNCENTRY
(
ceil
,
math_identity
)
{
LSTRKEY
(
"floor"
),
LFUNCVAL
(
math_identity
)},
LROT_FUNCENTRY
(
floor
,
math_identity
)
{
LSTRKEY
(
"max"
),
LFUNCVAL
(
math_max
)},
LROT_FUNCENTRY
(
max
,
math_max
)
{
LSTRKEY
(
"min"
),
LFUNCVAL
(
math_min
)},
LROT_FUNCENTRY
(
min
,
math_min
)
{
LSTRKEY
(
"pow"
),
LFUNCVAL
(
math_pow
)},
LROT_FUNCENTRY
(
pow
,
math_pow
)
{
LSTRKEY
(
"random"
),
LFUNCVAL
(
math_random
)},
LROT_FUNCENTRY
(
random
,
math_random
)
{
LSTRKEY
(
"randomseed"
),
LFUNCVAL
(
math_randomseed
)},
LROT_FUNCENTRY
(
randomseed
,
math_randomseed
)
{
LSTRKEY
(
"sqrt"
),
LFUNCVAL
(
math_sqrt
)},
LROT_FUNCENTRY
(
sqrt
,
math_sqrt
)
#if LUA_OPTIMIZE_MEMORY > 0
LROT_NUMENTRY
(
huge
,
INT_MAX
)
{
LSTRKEY
(
"huge"
),
LNUMVAL
(
LONG_MAX
)},
#endif
#else
#else
{
LSTRKEY
(
"abs"
),
LFUNCVAL
(
math_abs
)},
LROT_FUNCENTRY
(
abs
,
math_abs
)
// {LSTRKEY("acos"), LFUNCVAL(math_acos)},
// LROT_FUNCENTRY( acos, math_acos )
// {LSTRKEY("asin"), LFUNCVAL(math_asin)},
// LROT_FUNCENTRY( asin, math_asin )
// {LSTRKEY("atan2"), LFUNCVAL(math_atan2)},
// LROT_FUNCENTRY( atan2, math_atan2 )
// {LSTRKEY("atan"), LFUNCVAL(math_atan)},
// LROT_FUNCENTRY( atan, math_atan )
{
LSTRKEY
(
"ceil"
),
LFUNCVAL
(
math_ceil
)},
LROT_FUNCENTRY
(
ceil
,
math_ceil
)
// {LSTRKEY("cosh"), LFUNCVAL(math_cosh)},
// LROT_FUNCENTRY( cosh, math_cosh )
// {LSTRKEY("cos"), LFUNCVAL(math_cos)},
// LROT_FUNCENTRY( cos, math_cos )
// {LSTRKEY("deg"), LFUNCVAL(math_deg)},
// LROT_FUNCENTRY( deg, math_deg )
// {LSTRKEY("exp"), LFUNCVAL(math_exp)},
// LROT_FUNCENTRY( exp, math_exp )
{
LSTRKEY
(
"floor"
),
LFUNCVAL
(
math_floor
)},
LROT_FUNCENTRY
(
floor
,
math_floor
)
// {LSTRKEY("fmod"), LFUNCVAL(math_fmod)},
// LROT_FUNCENTRY( fmod, math_fmod )
#if LUA_OPTIMIZE_MEMORY > 0 && defined(LUA_COMPAT_MOD)
// LROT_FUNCENTRY( mod, math_fmod )
// {LSTRKEY("mod"), LFUNCVAL(math_fmod)},
// LROT_FUNCENTRY( frexp, math_frexp )
#endif
// LROT_FUNCENTRY( ldexp, math_ldexp )
// {LSTRKEY("frexp"), LFUNCVAL(math_frexp)},
// LROT_FUNCENTRY( log10, math_log10 )
// {LSTRKEY("ldexp"), LFUNCVAL(math_ldexp)},
// LROT_FUNCENTRY( log, math_log )
// {LSTRKEY("log10"), LFUNCVAL(math_log10)},
LROT_FUNCENTRY
(
max
,
math_max
)
// {LSTRKEY("log"), LFUNCVAL(math_log)},
LROT_FUNCENTRY
(
min
,
math_min
)
{
LSTRKEY
(
"max"
),
LFUNCVAL
(
math_max
)},
// LROT_FUNCENTRY( modf, math_modf )
{
LSTRKEY
(
"min"
),
LFUNCVAL
(
math_min
)},
LROT_FUNCENTRY
(
pow
,
math_pow
)
// {LSTRKEY("modf"), LFUNCVAL(math_modf)},
// LROT_FUNCENTRY( rad, math_rad )
{
LSTRKEY
(
"pow"
),
LFUNCVAL
(
math_pow
)},
LROT_FUNCENTRY
(
random
,
math_random
)
// {LSTRKEY("rad"), LFUNCVAL(math_rad)},
LROT_FUNCENTRY
(
randomseed
,
math_randomseed
)
{
LSTRKEY
(
"random"
),
LFUNCVAL
(
math_random
)},
// LROT_FUNCENTRY( sinh, math_sinh )
{
LSTRKEY
(
"randomseed"
),
LFUNCVAL
(
math_randomseed
)},
// LROT_FUNCENTRY( sin, math_sin )
// {LSTRKEY("sinh"), LFUNCVAL(math_sinh)},
LROT_FUNCENTRY
(
sqrt
,
math_sqrt
)
// {LSTRKEY("sin"), LFUNCVAL(math_sin)},
// LROT_FUNCENTRY( tanh, math_tanh )
{
LSTRKEY
(
"sqrt"
),
LFUNCVAL
(
math_sqrt
)},
// LROT_FUNCENTRY( tan, math_tan )
// {LSTRKEY("tanh"), LFUNCVAL(math_tanh)},
LROT_NUMENTRY
(
pi
,
PI
)
// {LSTRKEY("tan"), LFUNCVAL(math_tan)},
LROT_NUMENTRY
(
huge
,
HUGE_VAL
)
#if LUA_OPTIMIZE_MEMORY > 0
{
LSTRKEY
(
"pi"
),
LNUMVAL
(
PI
)},
{
LSTRKEY
(
"huge"
),
LNUMVAL
(
HUGE_VAL
)},
#endif // #if LUA_OPTIMIZE_MEMORY > 0
#endif // #ifdef LUA_NUMBER_INTEGRAL
#endif // #ifdef LUA_NUMBER_INTEGRAL
{
LNILKEY
,
LNILVAL
}
LROT_END
(
math
,
NULL
,
0
)
};
/*
/*
** Open math library
** Open math library
*/
*/
#if defined LUA_NUMBER_INTEGRAL
# include <limits.h>
/* for LONG_MAX */
#endif
LUALIB_API
int
luaopen_math
(
lua_State
*
L
)
{
LUALIB_API
int
luaopen_math
(
lua_State
*
L
)
{
#if LUA_OPTIMIZE_MEMORY > 0
return
0
;
return
0
;
#else
luaL_register
(
L
,
LUA_MATHLIBNAME
,
math_map
);
# if defined LUA_NUMBER_INTEGRAL
lua_pushnumber
(
L
,
LONG_MAX
);
lua_setfield
(
L
,
-
2
,
"huge"
);
# else
lua_pushnumber
(
L
,
PI
);
lua_setfield
(
L
,
-
2
,
"pi"
);
lua_pushnumber
(
L
,
HUGE_VAL
);
lua_setfield
(
L
,
-
2
,
"huge"
);
# if defined(LUA_COMPAT_MOD)
lua_getfield
(
L
,
-
1
,
"fmod"
);
lua_setfield
(
L
,
-
2
,
"mod"
);
# endif
# endif
return
1
;
#endif
}
}
components/lua/loadlib.c
View file @
eaac369d
...
@@ -20,7 +20,6 @@
...
@@ -20,7 +20,6 @@
#ifndef LUA_CROSS_COMPILER
#ifndef LUA_CROSS_COMPILER
#include "vfs.h"
#include "vfs.h"
#include "c_stdlib.h" // for c_getenv
#endif
#endif
#include "lauxlib.h"
#include "lauxlib.h"
...
@@ -334,9 +333,9 @@ static int ll_loadlib (lua_State *L) {
...
@@ -334,9 +333,9 @@ static int ll_loadlib (lua_State *L) {
*/
*/
#ifdef LUA_CROSS_COMPILER
#ifdef LUA_CROSS_COMPILER
static
int
readable
(
const
char
*
filename
)
{
static
int
readable
(
const
char
*
filename
)
{
FILE
*
f
=
c_
fopen
(
filename
,
"r"
);
/* try to open file */
FILE
*
f
=
fopen
(
filename
,
"r"
);
/* try to open file */
if
(
f
==
NULL
)
return
0
;
/* open failed */
if
(
f
==
NULL
)
return
0
;
/* open failed */
c_
fclose
(
f
);
fclose
(
f
);
return
1
;
return
1
;
}
}
#else
#else
...
@@ -363,7 +362,9 @@ static const char * findfile (lua_State *L, const char *name,
...
@@ -363,7 +362,9 @@ static const char * findfile (lua_State *L, const char *name,
const
char
*
pname
)
{
const
char
*
pname
)
{
const
char
*
path
;
const
char
*
path
;
name
=
luaL_gsub
(
L
,
name
,
"."
,
LUA_DIRSEP
);
name
=
luaL_gsub
(
L
,
name
,
"."
,
LUA_DIRSEP
);
lua_getfield
(
L
,
LUA_ENVIRONINDEX
,
pname
);
lua_getfield
(
L
,
LUA_GLOBALSINDEX
,
"package"
);
lua_getfield
(
L
,
-
1
,
pname
);
lua_remove
(
L
,
-
2
);
path
=
lua_tostring
(
L
,
-
1
);
path
=
lua_tostring
(
L
,
-
1
);
if
(
path
==
NULL
)
if
(
path
==
NULL
)
luaL_error
(
L
,
LUA_QL
(
"package.%s"
)
" must be a string"
,
pname
);
luaL_error
(
L
,
LUA_QL
(
"package.%s"
)
" must be a string"
,
pname
);
...
@@ -449,7 +450,9 @@ static int loader_Croot (lua_State *L) {
...
@@ -449,7 +450,9 @@ static int loader_Croot (lua_State *L) {
static
int
loader_preload
(
lua_State
*
L
)
{
static
int
loader_preload
(
lua_State
*
L
)
{
const
char
*
name
=
luaL_checkstring
(
L
,
1
);
const
char
*
name
=
luaL_checkstring
(
L
,
1
);
lua_getfield
(
L
,
LUA_ENVIRONINDEX
,
"preload"
);
lua_getfield
(
L
,
LUA_GLOBALSINDEX
,
"package"
);
lua_getfield
(
L
,
-
1
,
"preload"
);
lua_remove
(
L
,
-
2
);
if
(
!
lua_istable
(
L
,
-
1
))
if
(
!
lua_istable
(
L
,
-
1
))
luaL_error
(
L
,
LUA_QL
(
"package.preload"
)
" must be a table"
);
luaL_error
(
L
,
LUA_QL
(
"package.preload"
)
" must be a table"
);
lua_getfield
(
L
,
-
1
,
name
);
lua_getfield
(
L
,
-
1
,
name
);
...
@@ -475,13 +478,16 @@ static int ll_require (lua_State *L) {
...
@@ -475,13 +478,16 @@ static int ll_require (lua_State *L) {
return
1
;
/* package is already loaded */
return
1
;
/* package is already loaded */
}
}
/* Is this a readonly table? */
/* Is this a readonly table? */
void
*
res
=
luaR_findglobal
(
name
,
strlen
(
name
));
lua_getfield
(
L
,
LUA_GLOBALSINDEX
,
name
);
if
(
res
)
{
if
(
lua_isrotable
(
L
,
-
1
))
{
lua_pushrotable
(
L
,
res
);
return
1
;
return
1
;
}
else
{
lua_pop
(
L
,
1
);
}
}
/* else must load it; iterate over available loaders */
/* else must load it; iterate over available loaders */
lua_getfield
(
L
,
LUA_ENVIRONINDEX
,
"loaders"
);
lua_getfield
(
L
,
LUA_GLOBALSINDEX
,
"package"
);
lua_getfield
(
L
,
-
1
,
"loaders"
);
lua_remove
(
L
,
-
2
);
if
(
!
lua_istable
(
L
,
-
1
))
if
(
!
lua_istable
(
L
,
-
1
))
luaL_error
(
L
,
LUA_QL
(
"package.loaders"
)
" must be a table"
);
luaL_error
(
L
,
LUA_QL
(
"package.loaders"
)
" must be a table"
);
lua_pushliteral
(
L
,
""
);
/* error message accumulator */
lua_pushliteral
(
L
,
""
);
/* error message accumulator */
...
@@ -564,8 +570,13 @@ static void modinit (lua_State *L, const char *modname) {
...
@@ -564,8 +570,13 @@ static void modinit (lua_State *L, const char *modname) {
static
int
ll_module
(
lua_State
*
L
)
{
static
int
ll_module
(
lua_State
*
L
)
{
const
char
*
modname
=
luaL_checkstring
(
L
,
1
);
const
char
*
modname
=
luaL_checkstring
(
L
,
1
);
if
(
luaR_findglobal
(
modname
,
strlen
(
modname
)))
/* Is this a readonly table? */
lua_getfield
(
L
,
LUA_GLOBALSINDEX
,
modname
);
if
(
lua_isrotable
(
L
,
-
1
))
{
return
0
;
return
0
;
}
else
{
lua_pop
(
L
,
1
);
}
int
loaded
=
lua_gettop
(
L
)
+
1
;
/* index of _LOADED table */
int
loaded
=
lua_gettop
(
L
)
+
1
;
/* index of _LOADED table */
lua_getfield
(
L
,
LUA_REGISTRYINDEX
,
"_LOADED"
);
lua_getfield
(
L
,
LUA_REGISTRYINDEX
,
"_LOADED"
);
lua_getfield
(
L
,
loaded
,
modname
);
/* get _LOADED[modname] */
lua_getfield
(
L
,
loaded
,
modname
);
/* get _LOADED[modname] */
...
@@ -614,7 +625,7 @@ static int ll_seeall (lua_State *L) {
...
@@ -614,7 +625,7 @@ static int ll_seeall (lua_State *L) {
static
void
setpath
(
lua_State
*
L
,
const
char
*
fieldname
,
const
char
*
envname
,
static
void
setpath
(
lua_State
*
L
,
const
char
*
fieldname
,
const
char
*
envname
,
const
char
*
def
)
{
const
char
*
def
)
{
const
char
*
path
=
c_
getenv
(
envname
);
const
char
*
path
=
NULL
;
/*
getenv(envname)
not used in NodeMCU */
;
if
(
path
==
NULL
)
/* no environment variable? */
if
(
path
==
NULL
)
/* no environment variable? */
lua_pushstring
(
L
,
def
);
/* use default */
lua_pushstring
(
L
,
def
);
/* use default */
else
{
else
{
...
@@ -646,34 +657,20 @@ static const luaL_Reg ll_funcs[] = {
...
@@ -646,34 +657,20 @@ static const luaL_Reg ll_funcs[] = {
static
const
lua_CFunction
loaders
[]
=
static
const
lua_CFunction
loaders
[]
=
{
loader_preload
,
loader_Lua
,
loader_C
,
loader_Croot
,
NULL
};
{
loader_preload
,
loader_Lua
,
loader_C
,
loader_Croot
,
NULL
};
#if LUA_OPTIMIZE_MEMORY > 0
LROT_PUBLIC_BEGIN
(
lmt
)
#undef MIN_OPT_LEVEL
LROT_FUNCENTRY
(
__gc
,
gctm
)
#define MIN_OPT_LEVEL 1
LROT_END
(
lmt
,
lmt
,
LROT_MASK_GC
)
#include "lrodefs.h"
const
LUA_REG_TYPE
lmt
[]
=
{
{
LRO_STRKEY
(
"__gc"
),
LRO_FUNCVAL
(
gctm
)},
{
LRO_NILKEY
,
LRO_NILVAL
}
};
#endif
LUALIB_API
int
luaopen_package
(
lua_State
*
L
)
{
LUALIB_API
int
luaopen_package
(
lua_State
*
L
)
{
int
i
;
int
i
;
/* create new type _LOADLIB */
/* create new type _LOADLIB */
#if LUA_OPTIMIZE_MEMORY == 0
luaL_rometatable
(
L
,
"_LOADLIB"
,
LROT_TABLEREF
(
lmt
));
luaL_newmetatable
(
L
,
"_LOADLIB"
);
lua_pushlightfunction
(
L
,
gctm
);
lua_setfield
(
L
,
-
2
,
"__gc"
);
#else
luaL_rometatable
(
L
,
"_LOADLIB"
,
(
void
*
)
lmt
);
#endif
/* create `package' table */
/* create `package' table */
luaL_register_light
(
L
,
LUA_LOADLIBNAME
,
pk_funcs
);
luaL_register_light
(
L
,
LUA_LOADLIBNAME
,
pk_funcs
);
#if defined(LUA_COMPAT_LOADLIB)
#if defined(LUA_COMPAT_LOADLIB)
lua_getfield
(
L
,
-
1
,
"loadlib"
);
lua_getfield
(
L
,
-
1
,
"loadlib"
);
lua_setfield
(
L
,
LUA_GLOBALSINDEX
,
"loadlib"
);
lua_setfield
(
L
,
LUA_GLOBALSINDEX
,
"loadlib"
);
#endif
#endif
lua_pushvalue
(
L
,
-
1
);
lua_replace
(
L
,
LUA_ENVIRONINDEX
);
/* create `loaders' table */
/* create `loaders' table */
lua_createtable
(
L
,
sizeof
(
loaders
)
/
sizeof
(
loaders
[
0
])
-
1
,
0
);
lua_createtable
(
L
,
sizeof
(
loaders
)
/
sizeof
(
loaders
[
0
])
-
1
,
0
);
/* fill it with pre-defined loaders */
/* fill it with pre-defined loaders */
...
...
components/lua/lobject.c
View file @
eaac369d
...
@@ -54,6 +54,7 @@ int luaO_fb2int (int x) {
...
@@ -54,6 +54,7 @@ int luaO_fb2int (int x) {
int
luaO_log2
(
unsigned
int
x
)
{
int
luaO_log2
(
unsigned
int
x
)
{
#ifdef LUA_CROSS_COMPILER
static
const
lu_byte
log_2
[
256
]
=
{
static
const
lu_byte
log_2
[
256
]
=
{
0
,
1
,
2
,
2
,
3
,
3
,
3
,
3
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
0
,
1
,
2
,
2
,
3
,
3
,
3
,
3
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
6
,
...
@@ -67,6 +68,12 @@ int luaO_log2 (unsigned int x) {
...
@@ -67,6 +68,12 @@ int luaO_log2 (unsigned int x) {
int
l
=
-
1
;
int
l
=
-
1
;
while
(
x
>=
256
)
{
l
+=
8
;
x
>>=
8
;
}
while
(
x
>=
256
)
{
l
+=
8
;
x
>>=
8
;
}
return
l
+
log_2
[
x
];
return
l
+
log_2
[
x
];
#else
/* Use Normalization Shift Amount Unsigned: 0x1=>31 up to 0xffffffff =>0
* See Xtensa Instruction Set Architecture (ISA) Refman P 462 */
asm
volatile
(
"nsau %0, %1;"
:
"=r"
(
x
)
:
"r"
(
x
));
return
31
-
x
;
#endif
}
}
...
...
components/lua/lobject.h
View file @
eaac369d
...
@@ -19,10 +19,8 @@
...
@@ -19,10 +19,8 @@
#define NUM_TAGS (LAST_TAG+1)
#define NUM_TAGS (LAST_TAG+1)
/* mask for 'read-only' objects. must match READONLYBIT in lgc.h' */
#define READONLYMASK (1<<7)
/* denormalised bitmask for READONLYBIT and */
#define READONLYMASK 128
#define LFSMASK (1<<6)
/* LFSBIT to avoid include proliferation */
/*
/*
** Extra tags for non-values
** Extra tags for non-values
*/
*/
...
@@ -30,6 +28,21 @@
...
@@ -30,6 +28,21 @@
#define LUA_TUPVAL (LAST_TAG+2)
#define LUA_TUPVAL (LAST_TAG+2)
#define LUA_TDEADKEY (LAST_TAG+3)
#define LUA_TDEADKEY (LAST_TAG+3)
#ifdef __XTENSA__
/*
** force aligned access to critical fields in Flash-based structures
** wo is the offset of aligned word in bytes 0,4,8,..
** bo is the field within the word in bits 0..31
*/
#define GET_BYTE_FN(name,t,wo,bo) \
static inline lu_byte get ## name(void *o) { \
lu_byte res;
/* extract named field */
\
asm ("l32i %0, %1, " #wo "; extui %0, %0, " #bo ", 8;" : "=r"(res) : "r"(o) : );\
return res; }
#else
#define GET_BYTE_FN(name,t,wo,bo) \
static inline lu_byte get ## name(void *o) { return ((t *)o)->name; }
#endif
/*
/*
** Union of all collectable objects
** Union of all collectable objects
...
@@ -51,86 +64,46 @@ typedef struct GCheader {
...
@@ -51,86 +64,46 @@ typedef struct GCheader {
CommonHeader
;
CommonHeader
;
}
GCheader
;
}
GCheader
;
/*
** Word aligned inline access functions for the CommonHeader tt and marked fields.
** Note that these MUST be consistent with the CommonHeader definition above. Arg
** 3 is a word offset (4 bytes in this case) and arg 4 the bit offset in the word.
*/
GET_BYTE_FN
(
tt
,
GCheader
,
4
,
0
)
GET_BYTE_FN
(
marked
,
GCheader
,
4
,
8
)
#if defined(LUA_PACK_VALUE) || defined(ELUA_ENDIAN_BIG) || defined(ELUA_ENDIAN_SMALL)
# error "NodeMCU does not support the eLua LUA_PACK_VALUE and ELUA_ENDIAN defines"
#endif
/*
/*
** Union of all Lua values
** Union of all Lua values
*/
*/
#if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG )
typedef
union
{
struct
{
int
_pad0
;
GCObject
*
gc
;
};
struct
{
int
_pad1
;
void
*
p
;
};
lua_Number
n
;
struct
{
int
_pad2
;
int
b
;
};
}
Value
;
#else // #if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG )
typedef
union
{
typedef
union
{
GCObject
*
gc
;
GCObject
*
gc
;
void
*
p
;
void
*
p
;
lua_Number
n
;
lua_Number
n
;
int
b
;
int
b
;
}
Value
;
}
Value
;
#endif // #if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG )
/*
/*
** Tagged Values
** Tagged Values
*/
*/
#ifndef LUA_PACK_VALUE
#define TValuefields Value value; int tt
#define TValuefields Value value; int tt
#define LUA_TVALUE_NIL {NULL}, LUA_TNIL
#define LUA_TVALUE_NIL {NULL}, LUA_TNIL
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
#pragma pack(4)
#endif
typedef
struct
lua_TValue
{
typedef
struct
lua_TValue
{
TValuefields
;
TValuefields
;
}
TValue
;
}
TValue
;
#else // #ifndef LUA_PACK_VALUE
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
#ifdef ELUA_ENDIAN_LITTLE
#pragma pack()
#define TValuefields union { \
#endif
struct { \
int _pad0; \
int tt_sig; \
} _ts; \
struct { \
int _pad; \
short tt; \
short sig; \
} _t; \
Value value; \
}
#define LUA_TVALUE_NIL {0, add_sig(LUA_TNIL)}
#else // #ifdef ELUA_ENDIAN_LITTLE
#define TValuefields union { \
struct { \
int tt_sig; \
int _pad0; \
} _ts; \
struct { \
short sig; \
short tt; \
int _pad; \
} _t; \
Value value; \
}
#define LUA_TVALUE_NIL {add_sig(LUA_TNIL), 0}
#endif // #ifdef ELUA_ENDIAN_LITTLE
#define LUA_NOTNUMBER_SIG (-1)
#define add_sig(tt) ( 0xffff0000 | (tt) )
typedef
TValuefields
TValue
;
#endif // #ifndef LUA_PACK_VALUE
/* Macros to test type */
/* Macros to test type */
#ifndef LUA_PACK_VALUE
#define ttisnil(o) (ttype(o) == LUA_TNIL)
#define ttisnil(o) (ttype(o) == LUA_TNIL)
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
#define ttisstring(o) (ttype(o) == LUA_TSTRING)
#define ttisstring(o) (ttype(o) == LUA_TSTRING)
...
@@ -142,27 +115,11 @@ typedef TValuefields TValue;
...
@@ -142,27 +115,11 @@ typedef TValuefields TValue;
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
#define ttisrotable(o) (ttype(o) == LUA_TROTABLE)
#define ttisrotable(o) (ttype(o) == LUA_TROTABLE)
#define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION)
#define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION)
#else // #ifndef LUA_PACK_VALUE
#define ttisnil(o) (ttype_sig(o) == add_sig(LUA_TNIL))
#define ttisnumber(o) ((o)->_t.sig != LUA_NOTNUMBER_SIG)
#define ttisstring(o) (ttype_sig(o) == add_sig(LUA_TSTRING))
#define ttistable(o) (ttype_sig(o) == add_sig(LUA_TTABLE))
#define ttisfunction(o) (ttype_sig(o) == add_sig(LUA_TFUNCTION))
#define ttisboolean(o) (ttype_sig(o) == add_sig(LUA_TBOOLEAN))
#define ttisuserdata(o) (ttype_sig(o) == add_sig(LUA_TUSERDATA))
#define ttisthread(o) (ttype_sig(o) == add_sig(LUA_TTHREAD))
#define ttislightuserdata(o) (ttype_sig(o) == add_sig(LUA_TLIGHTUSERDATA))
#define ttisrotable(o) (ttype_sig(o) == add_sig(LUA_TROTABLE))
#define ttislightfunction(o) (ttype_sig(o) == add_sig(LUA_TLIGHTFUNCTION))
#endif // #ifndef LUA_PACK_VALUE
/* Macros to access values */
/* Macros to access values */
#ifndef LUA_PACK_VALUE
#define ttype(o) ((o)->tt)
#define ttype(o) ((void) (o)->value, (o)->tt)
#else // #ifndef LUA_PACK_VALUE
#define ttype(o) ((o)->_t.sig == LUA_NOTNUMBER_SIG ? (o)->_t.tt : LUA_TNUMBER)
#define ttype_sig(o) ((o)->_ts.tt_sig)
#endif // #ifndef LUA_PACK_VALUE
#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
#define rvalue(o) check_exp(ttisrotable(o), (o)->value.p)
#define rvalue(o) check_exp(ttisrotable(o), (o)->value.p)
...
@@ -182,24 +139,15 @@ typedef TValuefields TValue;
...
@@ -182,24 +139,15 @@ typedef TValuefields TValue;
/*
/*
** for internal debug only
** for internal debug only
*/
*/
#ifndef LUA_PACK_VALUE
#define checkconsistency(obj) \
#define checkconsistency(obj) \
lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
#define checkliveness(g,obj) \
#define checkliveness(g,obj) \
lua_assert(!iscollectable(obj) || \
lua_assert(!iscollectable(obj) || \
((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
#else // #ifndef LUA_PACK_VALUE
#define checkconsistency(obj) \
lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch._t.tt))
#define checkliveness(g,obj) \
lua_assert(!iscollectable(obj) || \
((ttype(obj) == (obj)->value.gc->gch._t.tt) && !isdead(g, (obj)->value.gc)))
#endif // #ifndef LUA_PACK_VALUE
/* Macros to set values */
/* Macros to set values */
#ifndef LUA_PACK_VALUE
#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
#define setnvalue(obj,x) \
#define setnvalue(obj,x) \
...
@@ -253,69 +201,10 @@ typedef TValuefields TValue;
...
@@ -253,69 +201,10 @@ typedef TValuefields TValue;
i_o->value.gc=i_x; i_o->tt=LUA_TPROTO; \
i_o->value.gc=i_x; i_o->tt=LUA_TPROTO; \
checkliveness(G(L),i_o); }
checkliveness(G(L),i_o); }
#define setobj(L,obj1,obj2) \
#define setobj(L,obj1,obj2) \
{ const TValue *o2=(obj2); TValue *o1=(obj1); \
{ const TValue *o2=(obj2); TValue *o1=(obj1); \
o1->value = o2->value; o1->tt=o2->tt; \
o1->value = o2->value; o1->tt=o2->tt; \
checkliveness(G(L),o1); }
checkliveness(G(L),o1); }
#else // #ifndef LUA_PACK_VALUE
#define setnilvalue(obj) ( ttype_sig(obj) = add_sig(LUA_TNIL) )
#define setnvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.n=(x); }
#define setpvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TLIGHTUSERDATA);}
#define setrvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TROTABLE);}
#define setfvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TLIGHTFUNCTION);}
#define setbvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.b=(x); i_o->_ts.tt_sig=add_sig(LUA_TBOOLEAN);}
#define setsvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TSTRING); \
checkliveness(G(L),i_o); }
#define setuvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TUSERDATA); \
checkliveness(G(L),i_o); }
#define setthvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TTHREAD); \
checkliveness(G(L),i_o); }
#define setclvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TFUNCTION); \
checkliveness(G(L),i_o); }
#define sethvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TTABLE); \
checkliveness(G(L),i_o); }
#define setptvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TPROTO); \
checkliveness(G(L),i_o); }
#define setobj(L,obj1,obj2) \
{ const TValue *o2=(obj2); TValue *o1=(obj1); \
o1->value = o2->value; \
checkliveness(G(L),o1); }
#endif // #ifndef LUA_PACK_VALUE
/*
/*
** different types of sets, according to destination
** different types of sets, according to destination
...
@@ -336,18 +225,11 @@ typedef TValuefields TValue;
...
@@ -336,18 +225,11 @@ typedef TValuefields TValue;
#define setobj2n setobj
#define setobj2n setobj
#define setsvalue2n setsvalue
#define setsvalue2n setsvalue
#ifndef LUA_PACK_VALUE
#define setttype(obj, stt) ((void) (obj)->value, (obj)->tt = (stt))
#define setttype(obj, tt) (ttype(obj) = (tt))
#else // #ifndef LUA_PACK_VALUE
/* considering it used only in lgc to set LUA_TDEADKEY */
/* we could define it this way */
#define setttype(obj, _tt) ( ttype_sig(obj) = add_sig(_tt) )
#endif // #ifndef LUA_PACK_VALUE
#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
typedef
TValue
*
StkId
;
/* index to stack elements */
typedef
TValue
*
StkId
;
/* index to stack elements */
...
@@ -363,8 +245,15 @@ typedef union TString {
...
@@ -363,8 +245,15 @@ typedef union TString {
}
tsv
;
}
tsv
;
}
TString
;
}
TString
;
#ifdef LUA_CROSS_COMPILER
#define getstr(ts) (((ts)->tsv.marked & READONLYMASK) ? cast(const char *, *(const char**)((ts) + 1)) : cast(const char *, (ts) + 1))
#define isreadonly(o) (0)
#else
#define isreadonly(o) ((o).marked & READONLYMASK)
#endif
#define ts_isreadonly(ts) isreadonly((ts)->tsv)
#define getstr(ts) (ts_isreadonly(ts) ? \
cast(const char *, *(const char**)((ts) + 1)) : \
cast(const char *, (ts) + 1))
#define svalue(o) getstr(rawtsvalue(o))
#define svalue(o) getstr(rawtsvalue(o))
...
@@ -414,6 +303,7 @@ typedef struct Proto {
...
@@ -414,6 +303,7 @@ typedef struct Proto {
lu_byte
is_vararg
;
lu_byte
is_vararg
;
lu_byte
maxstacksize
;
lu_byte
maxstacksize
;
}
Proto
;
}
Proto
;
#define proto_isreadonly(p) isreadonly(*(p))
/* masks for new-style vararg */
/* masks for new-style vararg */
...
@@ -483,7 +373,6 @@ typedef union Closure {
...
@@ -483,7 +373,6 @@ typedef union Closure {
** Tables
** Tables
*/
*/
#ifndef LUA_PACK_VALUE
typedef
union
TKey
{
typedef
union
TKey
{
struct
{
struct
{
TValuefields
;
TValuefields
;
...
@@ -493,16 +382,6 @@ typedef union TKey {
...
@@ -493,16 +382,6 @@ typedef union TKey {
}
TKey
;
}
TKey
;
#define LUA_TKEY_NIL {LUA_TVALUE_NIL, NULL}
#define LUA_TKEY_NIL {LUA_TVALUE_NIL, NULL}
#else // #ifndef LUA_PACK_VALUE
typedef
struct
TKey
{
TValue
tvk
;
struct
{
struct
Node
*
next
;
/* for chaining */
}
nk
;
}
TKey
;
#define LUA_TKEY_NIL {LUA_TVALUE_NIL}, {NULL}
#endif // #ifndef LUA_PACK_VALUE
typedef
struct
Node
{
typedef
struct
Node
{
TValue
i_val
;
TValue
i_val
;
...
@@ -522,6 +401,7 @@ typedef struct Table {
...
@@ -522,6 +401,7 @@ typedef struct Table {
int
sizearray
;
/* size of `array' array */
int
sizearray
;
/* size of `array' array */
}
Table
;
}
Table
;
typedef
const
struct
luaR_entry
ROTable
;
/*
/*
** `module' operation for hashing (size is always a power of 2)
** `module' operation for hashing (size is always a power of 2)
...
...
components/lua/lparser.c
View file @
eaac369d
...
@@ -10,7 +10,7 @@
...
@@ -10,7 +10,7 @@
#define LUAC_CROSS_FILE
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lua.h"
#include
C_HEADER_STRING
#include
<string.h>
#include "lcode.h"
#include "lcode.h"
#include "ldebug.h"
#include "ldebug.h"
...
@@ -916,12 +916,11 @@ static int block_follow (int token) {
...
@@ -916,12 +916,11 @@ static int block_follow (int token) {
static
void
block
(
LexState
*
ls
)
{
static
void
block
(
LexState
*
ls
)
{
/* block -> chunk */
/* block -> chunk */
FuncState
*
fs
=
ls
->
fs
;
FuncState
*
fs
=
ls
->
fs
;
BlockCnt
*
pbl
=
(
BlockCnt
*
)
luaM_malloc
(
ls
->
L
,
sizeof
(
BlockCnt
))
;
BlockCnt
bl
;
enterblock
(
fs
,
p
bl
,
0
);
enterblock
(
fs
,
&
bl
,
0
);
chunk
(
ls
);
chunk
(
ls
);
lua_assert
(
p
bl
->
breaklist
==
NO_JUMP
);
lua_assert
(
bl
.
breaklist
==
NO_JUMP
);
leaveblock
(
fs
);
leaveblock
(
fs
);
luaM_free
(
ls
->
L
,
pbl
);
}
}
...
@@ -1081,13 +1080,13 @@ static int exp1 (LexState *ls) {
...
@@ -1081,13 +1080,13 @@ static int exp1 (LexState *ls) {
static
void
forbody
(
LexState
*
ls
,
int
base
,
int
line
,
int
nvars
,
int
isnum
)
{
static
void
forbody
(
LexState
*
ls
,
int
base
,
int
line
,
int
nvars
,
int
isnum
)
{
/* forbody -> DO block */
/* forbody -> DO block */
BlockCnt
*
pbl
=
(
BlockCnt
*
)
luaM_malloc
(
ls
->
L
,
sizeof
(
BlockCnt
))
;
BlockCnt
bl
;
FuncState
*
fs
=
ls
->
fs
;
FuncState
*
fs
=
ls
->
fs
;
int
prep
,
endfor
;
int
prep
,
endfor
;
adjustlocalvars
(
ls
,
3
);
/* control variables */
adjustlocalvars
(
ls
,
3
);
/* control variables */
checknext
(
ls
,
TK_DO
);
checknext
(
ls
,
TK_DO
);
prep
=
isnum
?
luaK_codeAsBx
(
fs
,
OP_FORPREP
,
base
,
NO_JUMP
)
:
luaK_jump
(
fs
);
prep
=
isnum
?
luaK_codeAsBx
(
fs
,
OP_FORPREP
,
base
,
NO_JUMP
)
:
luaK_jump
(
fs
);
enterblock
(
fs
,
p
bl
,
0
);
/* scope for declared variables */
enterblock
(
fs
,
&
bl
,
0
);
/* scope for declared variables */
adjustlocalvars
(
ls
,
nvars
);
adjustlocalvars
(
ls
,
nvars
);
luaK_reserveregs
(
fs
,
nvars
);
luaK_reserveregs
(
fs
,
nvars
);
block
(
ls
);
block
(
ls
);
...
@@ -1097,7 +1096,6 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
...
@@ -1097,7 +1096,6 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
luaK_codeABC
(
fs
,
OP_TFORLOOP
,
base
,
0
,
nvars
);
luaK_codeABC
(
fs
,
OP_TFORLOOP
,
base
,
0
,
nvars
);
luaK_fixline
(
fs
,
line
);
/* pretend that `OP_FOR' starts the loop */
luaK_fixline
(
fs
,
line
);
/* pretend that `OP_FOR' starts the loop */
luaK_patchlist
(
fs
,
(
isnum
?
endfor
:
luaK_jump
(
fs
)),
prep
+
1
);
luaK_patchlist
(
fs
,
(
isnum
?
endfor
:
luaK_jump
(
fs
)),
prep
+
1
);
luaM_free
(
ls
->
L
,
pbl
);
}
}
...
...
components/lua/lrodefs.h
deleted
100644 → 0
View file @
7cb61a27
/* Read-only tables helper */
#ifndef lrodefs_h
#define lrodefs_h
#include "lrotable.h"
#undef LUA_REG_TYPE
#undef LSTRKEY
#undef LNILKEY
#undef LNUMKEY
#undef LFUNCVAL
#undef LNUMVAL
#undef LROVAL
#undef LNILVAL
#undef LREGISTER
#if (MIN_OPT_LEVEL > 0) && (LUA_OPTIMIZE_MEMORY >= MIN_OPT_LEVEL)
#define LUA_REG_TYPE luaR_entry
#define LSTRKEY LRO_STRKEY
#define LNUMKEY LRO_NUMKEY
#define LNILKEY LRO_NILKEY
#define LFUNCVAL LRO_FUNCVAL
#define LUDATA LRO_LUDATA
#define LNUMVAL LRO_NUMVAL
#define LROVAL LRO_ROVAL
#define LNILVAL LRO_NILVAL
#define LREGISTER(L, name, table)\
return 0
#else
#define LUA_REG_TYPE luaL_reg
#define LSTRKEY(x) x
#define LNILKEY NULL
#define LFUNCVAL(x) x
#define LNILVAL NULL
#define LREGISTER(L, name, table)\
luaL_register(L, name, table);\
return 1
#endif
#endif
/* lrodefs_h */
components/lua/lrotable.c
View file @
eaac369d
...
@@ -2,135 +2,157 @@
...
@@ -2,135 +2,157 @@
#define LUAC_CROSS_FILE
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lua.h"
#include
C_HEADER_STRING
#include
<string.h>
#include "lrotable.h"
#include "lrotable.h"
#include "lauxlib.h"
#include "lauxlib.h"
#include "lstring.h"
#include "lstring.h"
#include "lobject.h"
#include "lobject.h"
#include "lapi.h"
#include "lapi.h"
/* Local defines */
#ifdef _MSC_VER
#define LUAR_FINDFUNCTION 0
#define ALIGNED_STRING (__declspec( align( 4 ) ) char*)
#define LUAR_FINDVALUE 1
#else
#define ALIGNED_STRING (__attribute__((aligned(4))) char *)
/* Externally defined read-only table array */
#endif
extern
const
luaR_table
lua_rotable
[];
#define LA_LINES 32
#define LA_SLOTS 4
//#define COLLECT_STATS
/*
* All keyed ROtable access passes through luaR_findentry(). ROTables
* are simply a list of <key><TValue value> pairs. The existing algo
* did a linear scan of this vector of pairs looking for a match.
*
* A N×M lookaside cache has been added, with a simple hash on the key's
* TString addr and the ROTable addr to identify one of N lines. Each
* line has M slots which are scanned. This is all done in RAM and is
* perhaps 20x faster than the corresponding random Flash accesses which
* will cause flash faults.
*
* If a match is found and the table addresses match, then this entry is
* probed first. In practice the hit-rate here is over 99% so the code
* rarely fails back to doing the linear scan in ROM.
*
* Note that this hash does a couple of prime multiples and a modulus 2^X
* with is all evaluated in H/W, and adequately randomizes the lookup.
*/
#define HASH(a,b) ((((519*(size_t)(a)))>>4) + ((b) ? (b)->tsv.hash: 0))
static
struct
{
unsigned
hash
;
unsigned
addr
:
24
;
unsigned
ndx
:
8
;
}
cache
[
LA_LINES
][
LA_SLOTS
];
#ifdef COLLECT_STATS
unsigned
cache_stats
[
3
];
#define COUNT(i) cache_stats[i]++
#else
#define COUNT(i)
#endif
/* Find a global "read only table" in the constant lua_rotable array */
static
int
lookup_cache
(
unsigned
hash
,
ROTable
*
rotable
)
{
void
*
luaR_findglobal
(
const
char
*
name
,
unsigned
len
)
{
int
i
=
(
hash
>>
2
)
&
(
LA_LINES
-
1
),
j
;
unsigned
i
;
if
(
strlen
(
name
)
>
LUA_MAX_ROTABLE_NAME
)
for
(
j
=
0
;
j
<
LA_SLOTS
;
j
++
)
{
return
NULL
;
if
(
cache
[
i
][
j
].
hash
==
hash
&&
for
(
i
=
0
;
lua_rotable
[
i
].
name
;
i
++
)
((
size_t
)
rotable
&
0xffffffu
)
==
cache
[
i
][
j
].
addr
)
{
if
(
*
lua_rotable
[
i
].
name
!=
'\0'
&&
strlen
(
lua_rotable
[
i
].
name
)
==
len
&&
!
strncmp
(
lua_rotable
[
i
].
name
,
name
,
len
))
{
COUNT
(
0
);
return
(
void
*
)(
lua_rotable
[
i
].
pentries
)
;
return
cache
[
i
][
j
].
ndx
;
}
}
return
NULL
;
}
COUNT
(
1
);
return
-
1
;
}
}
/* Find an entry in a rotable and return it */
static
void
update_cache
(
unsigned
hash
,
ROTable
*
rotable
,
unsigned
ndx
)
{
static
const
TValue
*
luaR_auxfind
(
const
luaR_entry
*
pentry
,
const
char
*
strkey
,
luaR_numkey
numkey
,
unsigned
*
ppos
)
{
int
i
=
(
hash
)
>>
2
&
(
LA_LINES
-
1
),
j
;
const
TValue
*
res
=
NULL
;
COUNT
(
2
);
unsigned
i
=
0
;
if
(
ndx
>
0xffu
)
return
;
for
(
j
=
LA_SLOTS
-
1
;
j
>
0
;
j
--
)
cache
[
i
][
j
]
=
cache
[
i
][
j
-
1
];
cache
[
i
][
0
].
hash
=
hash
;
cache
[
i
][
0
].
addr
=
(
size_t
)
rotable
;
cache
[
i
][
0
].
ndx
=
ndx
;
}
/*
* Find a string key entry in a rotable and return it. Note that this internally
* uses a null key to denote a metatable search.
*/
const
TValue
*
luaR_findentry
(
ROTable
*
rotable
,
TString
*
key
,
unsigned
*
ppos
)
{
const
luaR_entry
*
pentry
=
rotable
;
const
char
*
strkey
=
key
?
getstr
(
key
)
:
ALIGNED_STRING
"__metatable"
;
unsigned
hash
=
HASH
(
rotable
,
key
);
if
(
pentry
==
NULL
)
unsigned
i
=
0
;
return
NULL
;
int
j
=
lookup_cache
(
hash
,
rotable
);
while
(
pentry
->
key
.
type
!=
LUA_TNIL
)
{
unsigned
l
=
key
?
key
->
tsv
.
len
:
sizeof
(
"__metatable"
)
-
1
;
if
((
strkey
&&
(
pentry
->
key
.
type
==
LUA_TSTRING
)
&&
(
!
strcmp
(
pentry
->
key
.
id
.
strkey
,
strkey
)))
||
(
!
strkey
&&
(
pentry
->
key
.
type
==
LUA_TNUMBER
)
&&
((
luaR_numkey
)
pentry
->
key
.
id
.
numkey
==
numkey
)))
{
if
(
pentry
)
{
res
=
&
pentry
->
value
;
if
(
j
>=
0
&&
!
strcmp
(
pentry
[
j
].
key
,
strkey
))
{
break
;
if
(
ppos
)
}
*
ppos
=
j
;
i
++
;
pentry
++
;
//printf("%3d hit %p %s\n", (hash>>2) & (LA_LINES-1), rotable, strkey);
return
&
pentry
[
j
].
value
;
}
}
if
(
res
&&
ppos
)
/*
* The invariants for 1st word comparison are deferred to here since they
* aren't needed if there is a cache hit. Note that the termination null
* is included so a "on\0" has a mask of 0xFFFFFF and "a\0" has 0xFFFF.
*/
unsigned
name4
,
mask4
=
l
>
2
?
(
~
0u
)
:
(
~
0u
)
>>
((
3
-
l
)
*
8
);
memcpy
(
&
name4
,
strkey
,
sizeof
(
name4
));
for
(;
pentry
->
key
!=
NULL
;
i
++
,
pentry
++
)
{
if
(((
*
(
unsigned
*
)
pentry
->
key
^
name4
)
&
mask4
)
==
0
&&
!
strcmp
(
pentry
->
key
,
strkey
))
{
//printf("%p %s hit after %d probes \n", rotable, strkey, (int)(pentry-rotable));
if
(
ppos
)
*
ppos
=
i
;
*
ppos
=
i
;
return
res
;
update_cache
(
hash
,
rotable
,
pentry
-
rotable
);
}
//printf("%3d %3d %p %s\n", (hash>>2) & (LA_LINES-1), (int)(pentry-rotable), rotable, strkey);
return
&
pentry
->
value
;
int
luaR_findfunction
(
lua_State
*
L
,
const
luaR_entry
*
ptable
)
{
const
TValue
*
res
=
NULL
;
const
char
*
key
=
luaL_checkstring
(
L
,
2
);
res
=
luaR_auxfind
(
ptable
,
key
,
0
,
NULL
);
if
(
res
&&
ttislightfunction
(
res
))
{
luaA_pushobject
(
L
,
res
);
return
1
;
}
}
else
}
return
0
;
}
}
//printf("%p %s miss after %d probes \n", rotable, strkey, (int)(pentry-rotable));
return
luaO_nilobject
;
/* Find an entry in a rotable and return its type
If "strkey" is not NULL, the function will look for a string key,
otherwise it will look for a number key */
const
TValue
*
luaR_findentry
(
void
*
data
,
const
char
*
strkey
,
luaR_numkey
numkey
,
unsigned
*
ppos
)
{
return
luaR_auxfind
((
const
luaR_entry
*
)
data
,
strkey
,
numkey
,
ppos
);
}
}
/* Find the metatable of a given table */
/* Find the metatable of a given table */
void
*
luaR_getmeta
(
void
*
data
)
{
void
*
luaR_getmeta
(
ROTable
*
rotable
)
{
#ifdef LUA_META_ROTABLES
const
TValue
*
res
=
luaR_findentry
(
rotable
,
NULL
,
NULL
);
const
TValue
*
res
=
luaR_auxfind
((
const
luaR_entry
*
)
data
,
"__metatable"
,
0
,
NULL
);
return
res
&&
ttisrotable
(
res
)
?
rvalue
(
res
)
:
NULL
;
return
res
&&
ttisrotable
(
res
)
?
rvalue
(
res
)
:
NULL
;
#else
return
NULL
;
#endif
}
}
static
void
luaR_next_helper
(
lua_State
*
L
,
const
luaR_entry
*
pentries
,
int
pos
,
TValue
*
key
,
TValue
*
val
)
{
static
void
luaR_next_helper
(
lua_State
*
L
,
ROTable
*
pentries
,
int
pos
,
setnilvalue
(
key
);
TValue
*
key
,
TValue
*
val
)
{
setnilvalue
(
val
);
if
(
pentries
[
pos
].
key
)
{
if
(
pentries
[
pos
].
key
.
type
!=
LUA_TNIL
)
{
/* Found an entry */
/* Found an entry */
if
(
pentries
[
pos
].
key
.
type
==
LUA_TSTRING
)
setsvalue
(
L
,
key
,
luaS_new
(
L
,
pentries
[
pos
].
key
));
setsvalue
(
L
,
key
,
luaS_newro
(
L
,
pentries
[
pos
].
key
.
id
.
strkey
))
else
setnvalue
(
key
,
(
lua_Number
)
pentries
[
pos
].
key
.
id
.
numkey
)
setobj2s
(
L
,
val
,
&
pentries
[
pos
].
value
);
setobj2s
(
L
,
val
,
&
pentries
[
pos
].
value
);
}
else
{
setnilvalue
(
key
);
setnilvalue
(
val
);
}
}
}
}
/* next (used for iteration) */
/* next (used for iteration) */
void
luaR_next
(
lua_State
*
L
,
void
*
data
,
TValue
*
key
,
TValue
*
val
)
{
void
luaR_next
(
lua_State
*
L
,
ROTable
*
rotable
,
TValue
*
key
,
TValue
*
val
)
{
const
luaR_entry
*
pentries
=
(
const
luaR_entry
*
)
data
;
char
strkey
[
LUA_MAX_ROTABLE_NAME
+
1
],
*
pstrkey
=
NULL
;
luaR_numkey
numkey
=
0
;
unsigned
keypos
;
unsigned
keypos
;
/* Special case: if key is nil, return the first element of the rotable */
/* Special case: if key is nil, return the first element of the rotable */
if
(
ttisnil
(
key
))
if
(
ttisnil
(
key
))
luaR_next_helper
(
L
,
pentries
,
0
,
key
,
val
);
luaR_next_helper
(
L
,
rotable
,
0
,
key
,
val
);
else
if
(
ttisstring
(
key
)
||
ttisnumber
(
key
)
)
{
else
if
(
ttisstring
(
key
))
{
/* Find the previou
d
key again */
/* Find the previou
s
key again */
if
(
ttisstring
(
key
))
{
if
(
ttisstring
(
key
))
{
luaR_getcstr
(
strkey
,
rawtsvalue
(
key
),
LUA_MAX_ROTABLE_NAME
);
luaR_findentry
(
rotable
,
rawtsvalue
(
key
),
&
keypos
);
pstrkey
=
strkey
;
}
}
else
numkey
=
(
luaR_numkey
)
nvalue
(
key
);
luaR_findentry
(
data
,
pstrkey
,
numkey
,
&
keypos
);
/* Advance to next key */
/* Advance to next key */
keypos
++
;
keypos
++
;
luaR_next_helper
(
L
,
pentries
,
keypos
,
key
,
val
);
luaR_next_helper
(
L
,
rotable
,
keypos
,
key
,
val
);
}
}
}
}
/* Convert a Lua string to a C string */
void
luaR_getcstr
(
char
*
dest
,
const
TString
*
src
,
size_t
maxsize
)
{
if
(
src
->
tsv
.
len
+
1
>
maxsize
)
dest
[
0
]
=
'\0'
;
else
{
memcpy
(
dest
,
getstr
(
src
),
src
->
tsv
.
len
);
dest
[
src
->
tsv
.
len
]
=
'\0'
;
}
}
/* Return 1 if the given pointer is a rotable */
#ifdef LUA_META_ROTABLES
#include "compiler.h"
int
luaR_isrotable
(
void
*
p
)
{
return
RODATA_START_ADDRESS
<=
(
char
*
)
p
&&
(
char
*
)
p
<=
RODATA_END_ADDRESS
;
}
#endif
components/lua/lrotable.h
View file @
eaac369d
...
@@ -4,35 +4,38 @@
...
@@ -4,35 +4,38 @@
#define lrotable_h
#define lrotable_h
#include "lua.h"
#include "lua.h"
#include "llimits.h"
#include "lobject.h"
#include "luaconf.h"
#include "luaconf.h"
#include "lobject.h"
#include "llimits.h"
/* Macros one can use to define rotable entries */
/* Macros one can use to define rotable entries */
#ifndef LUA_PACK_VALUE
#define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION}
#define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION}
#define LRO_LUDATA(v) {{.p = v}, LUA_TLIGHTUSERDATA}
#define LRO_LUDATA(v) {{.p = v}, LUA_TLIGHTUSERDATA}
#define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER}
#define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER}
#define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE}
#define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE}
#define LRO_NILVAL {{.p = NULL}, LUA_TNIL}
#define LRO_NILVAL {{.p = NULL}, LUA_TNIL}
#else // #ifndef LUA_PACK_VALUE
#define LRO_NUMVAL(v) {.value.n = v}
#ifdef LUA_CROSS_COMPILER
#ifdef ELUA_ENDIAN_LITTLE
#define LRO_STRKEY(k) k
#define LRO_FUNCVAL(v) {{(int)v, add_sig(LUA_TLIGHTFUNCTION)}}
#else
#define LRO_LUDATA(v) {{(int)v, add_sig(LUA_TLIGHTUSERDATA)}}
#define LRO_STRKEY(k) ((__attribute__((aligned(4))) char *) k)
#define LRO_ROVAL(v) {{(int)v, add_sig(LUA_TROTABLE)}}
#endif
#define LRO_NILVAL {{0, add_sig(LUA_TNIL)}}
#else // #ifdef ELUA_ENDIAN_LITTLE
#define LROT_TABLE(t) static const LUA_REG_TYPE t ## _map[];
#define LRO_FUNCVAL(v) {{add_sig(LUA_TLIGHTFUNCTION), (int)v}}
#define LROT_PUBLIC_TABLE(t) const LUA_REG_TYPE t ## _map[];
#define LRO_LUDATA(v) {{add_sig(LUA_TLIGHTUSERDATA), (int)v}}
#define LROT_TABLEREF(t) ((void *) t ## _map)
#define LRO_ROVAL(v) {{add_sig(LUA_TROTABLE), (int)v}}
#define LROT_BEGIN(t) static const LUA_REG_TYPE t ## _map [] = {
#define LRO_NILVAL {{add_sig(LUA_TNIL), 0}}
#define LROT_PUBLIC_BEGIN(t) const LUA_REG_TYPE t ## _map[] = {
#endif // #ifdef ELUA_ENDIAN_LITTLE
#define LROT_EXTERN(t) extern const LUA_REG_TYPE t ## _map[]
#endif // #ifndef LUA_PACK_VALUE
#define LROT_TABENTRY(n,t) {LRO_STRKEY(#n), LRO_ROVAL(t ## _map)},
#define LROT_FUNCENTRY(n,f) {LRO_STRKEY(#n), LRO_FUNCVAL(f)},
#define LRO_STRKEY(k) {LUA_TSTRING, {.strkey = k}}
#define LROT_NUMENTRY(n,x) {LRO_STRKEY(#n), LRO_NUMVAL(x)},
#define LRO_NUMKEY(k) {LUA_TNUMBER, {.numkey = k}}
#define LROT_LUDENTRY(n,x) {LRO_STRKEY(#n), LRO_LUDATA((void *) x)},
#define LRO_NILKEY {LUA_TNIL, {.strkey=NULL}}
#define LROT_END(t,mt, f) {NULL, LRO_NILVAL} };
#define LROT_BREAK(t) };
#define LUA_REG_TYPE luaR_entry
#define LREGISTER(L, name, table) return 0
/* Maximum length of a rotable name and of a string key*/
/* Maximum length of a rotable name and of a string key*/
#define LUA_MAX_ROTABLE_NAME 32
#define LUA_MAX_ROTABLE_NAME 32
...
@@ -40,41 +43,57 @@
...
@@ -40,41 +43,57 @@
/* Type of a numeric key in a rotable */
/* Type of a numeric key in a rotable */
typedef
int
luaR_numkey
;
typedef
int
luaR_numkey
;
/* The next structure defines the type of a key */
typedef
struct
{
int
type
;
union
{
const
char
*
strkey
;
luaR_numkey
numkey
;
}
id
;
}
luaR_key
;
/* An entry in the read only table */
/* An entry in the read only table */
typedef
struct
typedef
struct
luaR_entry
{
{
const
char
*
key
;
const
luaR_key
key
;
const
TValue
value
;
const
TValue
value
;
}
luaR_entry
;
}
luaR_entry
;
/* A rotable */
/*
typedef
struct
* The current ROTable implmentation is a vector of luaR_entry terminated by a
{
* nil record. The convention is to use ROtable * to refer to the entire vector
const
char
*
name
;
* as a logical ROTable.
const
luaR_entry
*
pentries
;
*/
}
luaR_table
;
typedef
const
struct
luaR_entry
ROTable
;
void
*
luaR_findglobal
(
const
char
*
key
,
unsigned
len
);
const
TValue
*
luaR_findentry
(
ROTable
*
tab
,
TString
*
key
,
unsigned
*
ppos
);
int
luaR_findfunction
(
lua_State
*
L
,
const
luaR_entry
*
ptable
);
const
TValue
*
luaR_findentryN
(
ROTable
*
tab
,
luaR_numkey
numkey
,
unsigned
*
ppos
);
const
TValue
*
luaR_findentry
(
void
*
data
,
const
char
*
strkey
,
luaR_numkey
numkey
,
unsigned
*
ppos
);
void
luaR_next
(
lua_State
*
L
,
ROTable
*
tab
,
TValue
*
key
,
TValue
*
val
);
void
luaR_getcstr
(
char
*
dest
,
const
TString
*
src
,
size_t
maxsize
);
void
*
luaR_getmeta
(
ROTable
*
tab
);
void
luaR_next
(
lua_State
*
L
,
void
*
data
,
TValue
*
key
,
TValue
*
val
);
void
*
luaR_getmeta
(
void
*
data
);
#ifdef LUA_META_ROTABLES
int
luaR_isrotable
(
void
*
p
);
int
luaR_isrotable
(
void
*
p
);
/*
* Set inRO check depending on platform. Note that this implementation needs
* to work on both the host (luac.cross) and ESP targets. The luac.cross
* VM is used for the -e option, and is primarily used to be able to debug
* VM changes on the more developer-friendly hot gdb environment.
*/
#if defined(LUA_CROSS_COMPILER)
#if defined(_MSC_VER)
//msvc build uses these dummy vars to locate the beginning and ending addresses of the RO data
extern
const
char
_ro_start
[],
_ro_end
[];
#define IN_RODATA_AREA(p) (((const char*)(p)) >= _ro_start && ((const char *)(p)) <= _ro_end)
#else
/* one of the POSIX variants */
#if defined(__CYGWIN__)
#define _RODATA_END __end__
#elif defined(__MINGW32__)
#define _RODATA_END end
#else
#else
#define
luaR_isrotable(p) (0)
#define
_RODATA_END _edata
#endif
#endif
extern
const
char
_RODATA_END
[];
#define IN_RODATA_AREA(p) (((const char *)(p)) < _RODATA_END)
#endif
/* defined(_MSC_VER) */
#else
/* xtensa tool chain for ESP32 target */
#include "compiler.h"
#define IN_RODATA_AREA(p) (((const char *)p) >= RODATA_START_ADDRESS && ((const char *)p) <= RODATA_END_ADDRESS)
#endif
/* defined(LUA_CROSS_COMPILER) */
/* Return 1 if the given pointer is a rotable */
#define luaR_isrotable(p) IN_RODATA_AREA(p)
#endif
#endif
components/lua/lstate.c
View file @
eaac369d
...
@@ -13,6 +13,7 @@
...
@@ -13,6 +13,7 @@
#include "ldebug.h"
#include "ldebug.h"
#include "ldo.h"
#include "ldo.h"
#include "lflash.h"
#include "lfunc.h"
#include "lfunc.h"
#include "lgc.h"
#include "lgc.h"
#include "llex.h"
#include "llex.h"
...
@@ -72,9 +73,12 @@ static void f_luaopen (lua_State *L, void *ud) {
...
@@ -72,9 +73,12 @@ static void f_luaopen (lua_State *L, void *ud) {
sethvalue
(
L
,
gt
(
L
),
luaH_new
(
L
,
0
,
2
));
/* table of globals */
sethvalue
(
L
,
gt
(
L
),
luaH_new
(
L
,
0
,
2
));
/* table of globals */
sethvalue
(
L
,
registry
(
L
),
luaH_new
(
L
,
0
,
2
));
/* registry */
sethvalue
(
L
,
registry
(
L
),
luaH_new
(
L
,
0
,
2
));
/* registry */
luaS_resize
(
L
,
MINSTRTABSIZE
);
/* initial size of string table */
luaS_resize
(
L
,
MINSTRTABSIZE
);
/* initial size of string table */
#ifndef LUA_CROSS_COMPILER
luaN_init
(
L
);
/* optionally map RO string table */
#endif
luaT_init
(
L
);
luaT_init
(
L
);
luaX_init
(
L
);
luaX_init
(
L
);
luaS_
fix
(
luaS_newliteral
(
L
,
MEMERRMSG
));
string
fix
(
luaS_newliteral
(
L
,
MEMERRMSG
));
g
->
GCthreshold
=
4
*
g
->
totalbytes
;
g
->
GCthreshold
=
4
*
g
->
totalbytes
;
}
}
...
@@ -191,6 +195,13 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
...
@@ -191,6 +195,13 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g
->
memlimit
=
EGC_INITIAL_MEMLIMIT
;
g
->
memlimit
=
EGC_INITIAL_MEMLIMIT
;
#else
#else
g
->
memlimit
=
0
;
g
->
memlimit
=
0
;
#endif
#ifndef LUA_CROSS_COMPILER
g
->
ROstrt
.
size
=
0
;
g
->
ROstrt
.
nuse
=
0
;
g
->
ROstrt
.
hash
=
NULL
;
g
->
ROpvmain
=
NULL
;
g
->
LFSsize
=
0
;
#endif
#endif
for
(
i
=
0
;
i
<
NUM_TAGS
;
i
++
)
g
->
mt
[
i
]
=
NULL
;
for
(
i
=
0
;
i
<
NUM_TAGS
;
i
++
)
g
->
mt
[
i
]
=
NULL
;
if
(
luaD_rawrunprotected
(
L
,
f_luaopen
,
NULL
)
!=
0
)
{
if
(
luaD_rawrunprotected
(
L
,
f_luaopen
,
NULL
)
!=
0
)
{
...
...
components/lua/lstate.h
View file @
eaac369d
...
@@ -82,7 +82,7 @@ typedef struct global_State {
...
@@ -82,7 +82,7 @@ typedef struct global_State {
Mbuffer
buff
;
/* temporary buffer for string concatentation */
Mbuffer
buff
;
/* temporary buffer for string concatentation */
lu_mem
GCthreshold
;
lu_mem
GCthreshold
;
lu_mem
totalbytes
;
/* number of bytes currently allocated */
lu_mem
totalbytes
;
/* number of bytes currently allocated */
l
u
_mem
memlimit
;
/* maximum number of bytes that can be allocated, 0 = no limit. */
l_mem
memlimit
;
/* maximum number of bytes that can be allocated, 0 = no limit.
<0 used with EGC_ON_MEM_LIMIT when free heap falls below -memlimit
*/
lu_mem
estimate
;
/* an estimate of number of bytes actually in use */
lu_mem
estimate
;
/* an estimate of number of bytes actually in use */
lu_mem
gcdept
;
/* how much GC is `behind schedule' */
lu_mem
gcdept
;
/* how much GC is `behind schedule' */
int
gcpause
;
/* size of pause between successive GCs */
int
gcpause
;
/* size of pause between successive GCs */
...
@@ -94,6 +94,11 @@ typedef struct global_State {
...
@@ -94,6 +94,11 @@ typedef struct global_State {
UpVal
uvhead
;
/* head of double-linked list of all open upvalues */
UpVal
uvhead
;
/* head of double-linked list of all open upvalues */
struct
Table
*
mt
[
NUM_TAGS
];
/* metatables for basic types */
struct
Table
*
mt
[
NUM_TAGS
];
/* metatables for basic types */
TString
*
tmname
[
TM_N
];
/* array with tag-method names */
TString
*
tmname
[
TM_N
];
/* array with tag-method names */
#ifndef LUA_CROSS_COMPILER
stringtable
ROstrt
;
/* Flash-based hash table for RO strings */
Proto
*
ROpvmain
;
/* Flash-based Proto main */
int
LFSsize
;
/* Size of Lua Flash Store */
#endif
}
global_State
;
}
global_State
;
...
...
components/lua/lstring.c
View file @
eaac369d
...
@@ -11,7 +11,7 @@
...
@@ -11,7 +11,7 @@
#define LUAC_CROSS_FILE
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lua.h"
#include
C_HEADER_STRING
#include
<string.h>
#include "lmem.h"
#include "lmem.h"
#include "lobject.h"
#include "lobject.h"
...
@@ -61,7 +61,7 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
...
@@ -61,7 +61,7 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
tb
=
&
G
(
L
)
->
strt
;
tb
=
&
G
(
L
)
->
strt
;
if
((
tb
->
nuse
+
1
)
>
cast
(
lu_int32
,
tb
->
size
)
&&
tb
->
size
<=
MAX_INT
/
2
)
if
((
tb
->
nuse
+
1
)
>
cast
(
lu_int32
,
tb
->
size
)
&&
tb
->
size
<=
MAX_INT
/
2
)
luaS_resize
(
L
,
tb
->
size
*
2
);
/* too crowded */
luaS_resize
(
L
,
tb
->
size
*
2
);
/* too crowded */
ts
=
cast
(
TString
*
,
luaM_malloc
(
L
,
readonly
?
sizeof
(
char
**
)
+
sizeof
(
TString
)
:
(
l
+
1
)
*
sizeof
(
char
)
+
sizeof
(
TString
)));
ts
=
cast
(
TString
*
,
luaM_malloc
(
L
,
sizeof
(
TString
)
+
(
readonly
?
sizeof
(
char
**
)
:
(
l
+
1
)
*
sizeof
(
char
))));
ts
->
tsv
.
len
=
l
;
ts
->
tsv
.
len
=
l
;
ts
->
tsv
.
hash
=
h
;
ts
->
tsv
.
hash
=
h
;
ts
->
tsv
.
marked
=
luaC_white
(
G
(
L
));
ts
->
tsv
.
marked
=
luaC_white
(
G
(
L
));
...
@@ -71,7 +71,7 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
...
@@ -71,7 +71,7 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
((
char
*
)(
ts
+
1
))[
l
]
=
'\0'
;
/* ending 0 */
((
char
*
)(
ts
+
1
))[
l
]
=
'\0'
;
/* ending 0 */
}
else
{
}
else
{
*
(
char
**
)(
ts
+
1
)
=
(
char
*
)
str
;
*
(
char
**
)(
ts
+
1
)
=
(
char
*
)
str
;
l
uaS_readonly
(
ts
);
l
_setbit
((
ts
)
->
tsv
.
marked
,
READONLYBIT
);
}
}
h
=
lmod
(
h
,
tb
->
size
);
h
=
lmod
(
h
,
tb
->
size
);
ts
->
tsv
.
next
=
tb
->
hash
[
h
];
/* chain new entry */
ts
->
tsv
.
next
=
tb
->
hash
[
h
];
/* chain new entry */
...
@@ -80,14 +80,28 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
...
@@ -80,14 +80,28 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
return
ts
;
return
ts
;
}
}
static
int
lua_is_ptr_in_ro_area
(
const
char
*
p
)
{
#ifdef LUA_CROSS_COMPILER
return
0
;
// TStrings are never in RO in luac.cross
#else
return
IN_RODATA_AREA
(
p
);
#endif
}
/*
* The string algorithm has been modified to be LFS-friendly. The previous eLua
* algo used the address of the string was in flash and the string was >4 bytes
* This creates miminal savings and prevents the use of LFS based strings
*/
static
TString
*
luaS_newlstr
_helper
(
lua_State
*
L
,
const
char
*
str
,
size_t
l
,
int
readonly
)
{
LUAI_FUNC
TString
*
luaS_newlstr
(
lua_State
*
L
,
const
char
*
str
,
size_t
l
)
{
GCObject
*
o
;
GCObject
*
o
;
unsigned
int
h
=
cast
(
unsigned
int
,
l
);
/* seed */
unsigned
int
h
=
cast
(
unsigned
int
,
l
);
/* seed */
size_t
step
=
(
l
>>
5
)
+
1
;
/* if string is too long, don't hash all its chars */
size_t
step
=
(
l
>>
5
)
+
1
;
/* if string is too long, don't hash all its chars */
size_t
l1
;
size_t
l1
;
for
(
l1
=
l
;
l1
>=
step
;
l1
-=
step
)
/* compute hash */
for
(
l1
=
l
;
l1
>=
step
;
l1
-=
step
)
/* compute hash */
h
=
h
^
((
h
<<
5
)
+
(
h
>>
2
)
+
cast
(
unsigned
char
,
str
[
l1
-
1
]));
h
=
h
^
((
h
<<
5
)
+
(
h
>>
2
)
+
cast
(
unsigned
char
,
str
[
l1
-
1
]));
for
(
o
=
G
(
L
)
->
strt
.
hash
[
lmod
(
h
,
G
(
L
)
->
strt
.
size
)];
for
(
o
=
G
(
L
)
->
strt
.
hash
[
lmod
(
h
,
G
(
L
)
->
strt
.
size
)];
o
!=
NULL
;
o
!=
NULL
;
o
=
o
->
gch
.
next
)
{
o
=
o
->
gch
.
next
)
{
...
@@ -98,35 +112,27 @@ static TString *luaS_newlstr_helper (lua_State *L, const char *str, size_t l, in
...
@@ -98,35 +112,27 @@ static TString *luaS_newlstr_helper (lua_State *L, const char *str, size_t l, in
return
ts
;
return
ts
;
}
}
}
}
return
newlstr
(
L
,
str
,
l
,
h
,
readonly
);
/* not found */
#ifndef LUA_CROSS_COMPILER
}
/*
* The RAM strt is searched first since RAM access is faster tham Flash access.
static
int
lua_is_ptr_in_ro_area
(
const
char
*
p
)
{
* If a miss, then search the RO string table.
#ifdef LUA_CROSS_COMPILER
*/
return
0
;
if
(
G
(
L
)
->
ROstrt
.
hash
)
{
#else
for
(
o
=
G
(
L
)
->
ROstrt
.
hash
[
lmod
(
h
,
G
(
L
)
->
ROstrt
.
size
)];
o
!=
NULL
;
#include "compiler.h"
o
=
o
->
gch
.
next
)
{
TString
*
ts
=
rawgco2ts
(
o
);
return
p
>=
RODATA_START_ADDRESS
&&
p
<=
RODATA_END_ADDRESS
;
if
(
ts
->
tsv
.
len
==
l
&&
(
memcmp
(
str
,
getstr
(
ts
),
l
)
==
0
))
{
return
ts
;
}
}
}
#endif
#endif
}
/* New additions to the RAM strt are tagged as readonly if the string address
* is in the CTEXT segment (target only, not luac.cross) */
TString
*
luaS_newlstr
(
lua_State
*
L
,
const
char
*
str
,
size_t
l
)
{
int
readonly
=
(
lua_is_ptr_in_ro_area
(
str
)
&&
l
+
1
>
sizeof
(
char
**
)
&&
// If the pointer is in a read-only memory and the string is at least 4 chars in length,
l
==
strlen
(
str
)
?
LUAS_READONLY_STRING
:
LUAS_REGULAR_STRING
);
// create it as a read-only string instead
return
newlstr
(
L
,
str
,
l
,
h
,
readonly
);
/* not found */
if
(
lua_is_ptr_in_ro_area
(
str
)
&&
l
+
1
>
sizeof
(
char
**
)
&&
l
==
strlen
(
str
))
return
luaS_newlstr_helper
(
L
,
str
,
l
,
LUAS_READONLY_STRING
);
else
return
luaS_newlstr_helper
(
L
,
str
,
l
,
LUAS_REGULAR_STRING
);
}
LUAI_FUNC
TString
*
luaS_newrolstr
(
lua_State
*
L
,
const
char
*
str
,
size_t
l
)
{
if
(
l
+
1
>
sizeof
(
char
**
)
&&
l
==
strlen
(
str
))
return
luaS_newlstr_helper
(
L
,
str
,
l
,
LUAS_READONLY_STRING
);
else
// no point in creating a RO string, as it would actually be larger
return
luaS_newlstr_helper
(
L
,
str
,
l
,
LUAS_REGULAR_STRING
);
}
}
...
...
components/lua/lstring.h
View file @
eaac369d
...
@@ -13,22 +13,16 @@
...
@@ -13,22 +13,16 @@
#include "lstate.h"
#include "lstate.h"
#define sizestring(s) (sizeof(union TString)+(
luaS_isreadonly(s
) ? sizeof(char **) : ((s)->len+1)*sizeof(char)))
#define sizestring(s) (sizeof(union TString)+(
testbit(getmarked(s), READONLYBIT
) ? sizeof(char **) : ((s)->len+1)*sizeof(char)))
#define sizeudata(u) (sizeof(union Udata)+(u)->len)
#define sizeudata(u) (sizeof(union Udata)+(u)->len)
#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
#define luaS_newro(L, s) (luaS_newrolstr(L, s, strlen(s)))
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
(sizeof(s)/sizeof(char))-1))
(sizeof(s)/sizeof(char))-1))
#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT)
#define luaS_readonly(s) l_setbit((s)->tsv.marked, READONLYBIT)
#define luaS_isreadonly(s) testbit((s)->marked, READONLYBIT)
LUAI_FUNC
void
luaS_resize
(
lua_State
*
L
,
int
newsize
);
LUAI_FUNC
void
luaS_resize
(
lua_State
*
L
,
int
newsize
);
LUAI_FUNC
Udata
*
luaS_newudata
(
lua_State
*
L
,
size_t
s
,
Table
*
e
);
LUAI_FUNC
Udata
*
luaS_newudata
(
lua_State
*
L
,
size_t
s
,
Table
*
e
);
LUAI_FUNC
TString
*
luaS_newlstr
(
lua_State
*
L
,
const
char
*
str
,
size_t
l
);
LUAI_FUNC
TString
*
luaS_newlstr
(
lua_State
*
L
,
const
char
*
str
,
size_t
l
);
LUAI_FUNC
TString
*
luaS_newrolstr
(
lua_State
*
L
,
const
char
*
str
,
size_t
l
);
#endif
#endif
components/lua/lstrlib.c
View file @
eaac369d
...
@@ -10,8 +10,8 @@
...
@@ -10,8 +10,8 @@
#define LUAC_CROSS_FILE
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lua.h"
#include
C_HEADER_STDIO
#include
<stdio.h>
#include
C_HEADER_STRING
#include
<string.h>
#include "lauxlib.h"
#include "lauxlib.h"
#include "lualib.h"
#include "lualib.h"
...
@@ -577,7 +577,7 @@ static int gmatch (lua_State *L) {
...
@@ -577,7 +577,7 @@ static int gmatch (lua_State *L) {
return
1
;
return
1
;
}
}
#if
LUA_OPTIMIZE_MEMORY == 0 || !defined(
LUA_COMPAT_GFIND
)
#if
ndef
LUA_COMPAT_GFIND
static
int
gfind_nodef
(
lua_State
*
L
)
{
static
int
gfind_nodef
(
lua_State
*
L
)
{
return
luaL_error
(
L
,
LUA_QL
(
"string.gfind"
)
" was renamed to "
return
luaL_error
(
L
,
LUA_QL
(
"string.gfind"
)
" was renamed to "
LUA_QL
(
"string.gmatch"
));
LUA_QL
(
"string.gmatch"
));
...
@@ -825,67 +825,37 @@ static int str_format (lua_State *L) {
...
@@ -825,67 +825,37 @@ static int str_format (lua_State *L) {
return
1
;
return
1
;
}
}
#undef MIN_OPT_LEVEL
LROT_PUBLIC_BEGIN
(
strlib
)
#define MIN_OPT_LEVEL 1
LROT_FUNCENTRY
(
byte
,
str_byte
)
#include "lrodefs.h"
LROT_FUNCENTRY
(
char
,
str_char
)
const
LUA_REG_TYPE
strlib
[]
=
{
LROT_FUNCENTRY
(
dump
,
str_dump
)
{
LSTRKEY
(
"byte"
),
LFUNCVAL
(
str_byte
)},
LROT_FUNCENTRY
(
find
,
str_find
)
{
LSTRKEY
(
"char"
),
LFUNCVAL
(
str_char
)},
LROT_FUNCENTRY
(
format
,
str_format
)
{
LSTRKEY
(
"dump"
),
LFUNCVAL
(
str_dump
)},
#ifdef LUA_COMPAT_GFIND
{
LSTRKEY
(
"find"
),
LFUNCVAL
(
str_find
)},
LROT_FUNCENTRY
(
gfind
,
gmatch
)
{
LSTRKEY
(
"format"
),
LFUNCVAL
(
str_format
)},
#if LUA_OPTIMIZE_MEMORY > 0 && defined(LUA_COMPAT_GFIND)
{
LSTRKEY
(
"gfind"
),
LFUNCVAL
(
gmatch
)},
#else
#else
{
LSTRKEY
(
"gfind"
),
LFUNCVAL
(
gfind_nodef
)},
LROT_FUNCENTRY
(
gfind
,
gfind_nodef
)
#endif
{
LSTRKEY
(
"gmatch"
),
LFUNCVAL
(
gmatch
)},
{
LSTRKEY
(
"gsub"
),
LFUNCVAL
(
str_gsub
)},
{
LSTRKEY
(
"len"
),
LFUNCVAL
(
str_len
)},
{
LSTRKEY
(
"lower"
),
LFUNCVAL
(
str_lower
)},
{
LSTRKEY
(
"match"
),
LFUNCVAL
(
str_match
)},
{
LSTRKEY
(
"rep"
),
LFUNCVAL
(
str_rep
)},
{
LSTRKEY
(
"reverse"
),
LFUNCVAL
(
str_reverse
)},
{
LSTRKEY
(
"sub"
),
LFUNCVAL
(
str_sub
)},
{
LSTRKEY
(
"upper"
),
LFUNCVAL
(
str_upper
)},
#if LUA_OPTIMIZE_MEMORY > 0
{
LSTRKEY
(
"__index"
),
LROVAL
(
strlib
)},
#endif
{
LNILKEY
,
LNILVAL
}
};
#if LUA_OPTIMIZE_MEMORY != 2
static
void
createmetatable
(
lua_State
*
L
)
{
lua_createtable
(
L
,
0
,
1
);
/* create metatable for strings */
lua_pushliteral
(
L
,
""
);
/* dummy string */
lua_pushvalue
(
L
,
-
2
);
lua_setmetatable
(
L
,
-
2
);
/* set string metatable */
lua_pop
(
L
,
1
);
/* pop dummy string */
lua_pushvalue
(
L
,
-
2
);
/* string library... */
lua_setfield
(
L
,
-
2
,
"__index"
);
/* ...is the __index metamethod */
lua_pop
(
L
,
1
);
/* pop metatable */
}
#endif
#endif
LROT_FUNCENTRY
(
gmatch
,
gmatch
)
LROT_FUNCENTRY
(
gsub
,
str_gsub
)
LROT_FUNCENTRY
(
len
,
str_len
)
LROT_FUNCENTRY
(
lower
,
str_lower
)
LROT_FUNCENTRY
(
match
,
str_match
)
LROT_FUNCENTRY
(
rep
,
str_rep
)
LROT_FUNCENTRY
(
reverse
,
str_reverse
)
LROT_FUNCENTRY
(
sub
,
str_sub
)
LROT_FUNCENTRY
(
upper
,
str_upper
)
LROT_TABENTRY
(
__index
,
strlib
)
LROT_END
(
strlib
,
NULL
,
0
)
// OR DO WE NEED LRTO_MASK_INDEX **TODO**
/*
/*
** Open string library
** Open string library
*/
*/
LUALIB_API
int
luaopen_string
(
lua_State
*
L
)
{
LUALIB_API
int
luaopen_string
(
lua_State
*
L
)
{
#if LUA_OPTIMIZE_MEMORY == 0
luaL_register
(
L
,
LUA_STRLIBNAME
,
strlib
);
#if defined(LUA_COMPAT_GFIND)
lua_getfield
(
L
,
-
1
,
"gmatch"
);
lua_setfield
(
L
,
-
2
,
"gfind"
);
#endif
createmetatable
(
L
);
return
1
;
#else
lua_pushliteral
(
L
,
""
);
lua_pushliteral
(
L
,
""
);
lua_pushrotable
(
L
,
(
void
*
)
strlib
);
lua_pushrotable
(
L
,
LROT_TABLEREF
(
strlib
)
)
;
lua_setmetatable
(
L
,
-
2
);
lua_setmetatable
(
L
,
-
2
);
lua_pop
(
L
,
1
);
lua_pop
(
L
,
1
);
return
0
;
return
0
;
#endif
}
}
Prev
1
2
3
4
5
6
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment