Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
libhxcpp 6.0.0 (unreleased)
------------------------------------------------------------

* Fixed an exception from blit, setSize or resize under the cppia JIT ending the process instead of reaching the script's catch, on typed arrays and on Array<Dynamic>: their native calls had no exception bridge. The script catches it, as it does interpreted and in compiled code (libhxcpp #404)
* Fixed resize() and cpp.NativeArray.setSize() on an Array<Dynamic> under the cppia JIT evaluating the array expression twice, so a call in it ran twice and the array it returned the second time was the one resized. The JIT evaluates it once (libhxcpp #411)
* Fixed indexOf and lastIndexOf on an Array<Dynamic> under the cppia JIT ignoring fromIndex: the JIT never generated it, so a call or exception in it was lost too. The search starts from it, as it does interpreted and in compiled code (libhxcpp #410)
* Fixed reverse() and resize() on an Array<Dynamic> in interpreted cppia doing nothing: the interpreter had no case for them, and resize never evaluated its argument. They reverse and resize the array, as they do under the JIT and in compiled code (libhxcpp #409)
* Added HXCPP_PROGRESS_PERCENT, which shows a group's compile progress as a percentage of its files, [42.5% ], instead of a count, [425/1000]
* Fixed a program on Linux with glibc staying as large as its largest burst of large allocations, such as the files a game reads while it loads: glibc keeps a freed buffer's memory in its heap unless it had mapped the buffer on its own, and once a buffer mapped on its own has been freed it stops mapping those of that size or less, up to 32 MB. The memory of the large buffers a collection freed then stayed the process's. The collector now trims the C heap once 16 MB has been freed to it, on the thread that frees the buffers. A program that dropped 384 MB of 4 MB buffers stayed at 396 MB resident and now returns to 12 MB
* Fixed a native extension that includes hx/CFFI.h before hx/CFFIPrime.h, as SteamWrap does, failing to compile with hxs_encoding, hxs_utf16 and alloc_hxs_utf8 not declared: CFFI.h included first declares the CFFI API without HXCPP_PRIME, so without the Prime string functions that the ordinary wrapper of a DEFINE_PRIME function now uses. CFFIPrime.h declares them then
Expand Down
56 changes: 35 additions & 21 deletions src/hx/cppia/ArrayBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,35 @@ static ArrayBase * SLJIT_CALL array_expand_size(ArrayBase *inArray, int inSize)
return inArray;
}

// blit, __SetSizeExact and resize throw for a range or size the array cannot
// take, and the exception becomes the script's pending one, which the code
// after the call checks. They are ArrayBase's whatever the element type, so
// each is one function here: a copy for every element type and builtin, each
// with its own exception handling, would take more sections than MSVC's
// object file format allows.
static void SLJIT_CALL array_set_size_exact(ArrayBase *inArray, int inSize)
{
TRY_NATIVE
inArray->__SetSizeExact(inSize);
CATCH_NATIVE
}

static void SLJIT_CALL array_resize(ArrayBase *inArray, int inSize)
{
TRY_NATIVE
inArray->resize(inSize);
CATCH_NATIVE
}

static void SLJIT_CALL array_blit(JitMultiArg *inArgs)
{
// this, inDestElement, inSourceArray, inSourceElement, inElementCount
TRY_NATIVE
ArrayBase *dest = (ArrayBase *)inArgs[0].obj;
dest->Blit( inArgs[1].ival, (ArrayBase *)inArgs[2].obj, inArgs[3].ival, inArgs[4].ival );
CATCH_NATIVE
}

#endif


Expand Down Expand Up @@ -1245,16 +1274,6 @@ struct ArrayBuiltin : public ArrayBuiltinBase
return inArray->keyValueIterator().mPtr;
}

static void SLJIT_CALL runSetSizeExact( Array_obj<ELEM> *inArray, int size )
{
inArray->__SetSizeExact(size);
}

static void SLJIT_CALL runResize( Array_obj<ELEM> *inArray, int size )
{
inArray->resize(size);
}


static void SLJIT_CALL runToString( Array_obj<ELEM> *inArray, String *outString )
{
Expand All @@ -1268,14 +1287,6 @@ struct ArrayBuiltin : public ArrayBuiltinBase
return inArray->copy().mPtr;
}

static void SLJIT_CALL runBlit( JitMultiArg *inArgs)
{
// this, inDestElement, inSourceArray, inSourceElement, inElementCount
Array_obj<ELEM> *dest = (Array_obj<ELEM> *)inArgs[0].obj;
Array_obj<ELEM> *src = (Array_obj<ELEM> *)inArgs[2].obj;
dest->blit( inArgs[1].ival, src, inArgs[3].ival, inArgs[4].ival );
}


static hx::Object * SLJIT_CALL runProcess( Array_obj<ELEM> *inArray, hx::Object *inFunction)
{
Expand Down Expand Up @@ -1891,7 +1902,8 @@ struct ArrayBuiltin : public ArrayBuiltinBase
thisExpr->genCode(compiler, thisVal, etObject);
genNullReferenceExceptionCheck(compiler, thisVal);
args[0]->genCode(compiler, sJitArg1.as(jtInt), etInt);
compiler->callNative( (void *)runSetSizeExact, thisVal, sJitArg1.as(jtInt));
compiler->callNative( (void *)array_set_size_exact, thisVal, sJitArg1.as(jtInt));
compiler->checkException();
break;
}

Expand All @@ -1901,7 +1913,8 @@ struct ArrayBuiltin : public ArrayBuiltinBase
thisExpr->genCode(compiler, thisVal, etObject);
genNullReferenceExceptionCheck(compiler, thisVal);
args[0]->genCode(compiler, sJitArg1.as(jtInt), etInt);
compiler->callNative( (void *)runResize, thisVal, sJitArg1.as(jtInt));
compiler->callNative( (void *)array_resize, thisVal, sJitArg1.as(jtInt));
compiler->checkException();
break;
}

Expand All @@ -1916,7 +1929,8 @@ struct ArrayBuiltin : public ArrayBuiltinBase
args[1]->genCode(compiler, fargs.arg(2,jtPointer), etObject);
args[2]->genCode(compiler, fargs.arg(3,jtInt), etInt);
args[3]->genCode(compiler, fargs.arg(4,jtInt), etInt);
compiler->callNative( (void *)runBlit, fargs );
compiler->callNative( (void *)array_blit, fargs );
compiler->checkException();
break;
}

Expand Down
71 changes: 50 additions & 21 deletions src/hx/cppia/ArrayVirtual.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,19 @@ static hx::Object * SLJIT_CALL arrayConcat(ArrayAnyImpl *inObj, hx::Object *inVa
{
return inObj->concat(Dynamic(inValue)).mPtr;
}
// These throw for a size or range the array cannot take: the exception becomes
// the script's pending one, which the code after the call checks
static void SLJIT_CALL arraySetSizeExact(ArrayAnyImpl *inObj, int inSize)
{
TRY_NATIVE
inObj->__SetSizeExact(inSize);
CATCH_NATIVE
}
static void SLJIT_CALL arrayResize(ArrayAnyImpl *inObj, int inSize)
{
TRY_NATIVE
inObj->resize(inSize);
CATCH_NATIVE
}


Expand Down Expand Up @@ -142,9 +148,11 @@ static void SLJIT_CALL arrayUnshiftString( ArrayAnyImpl *inArray, String *inVal)
static void SLJIT_CALL runBlit( JitMultiArg *inArgs)
{
// this, inDestElement, inSourceArray, inSourceElement, inElementCount
TRY_NATIVE
ArrayAnyImpl *dest = (ArrayAnyImpl *)inArgs[0].obj;
ArrayAnyImpl *src = (ArrayAnyImpl *)inArgs[2].obj;
dest->blit( inArgs[1].ival, src, inArgs[3].ival, inArgs[4].ival );
CATCH_NATIVE
}


Expand Down Expand Up @@ -261,7 +269,8 @@ struct ArrayBuiltinAny : public ArrayBuiltinBase
if (FUNC==afJoin || FUNC==afToString)
return Dynamic(runString(ctx)).mPtr;

if (FUNC==afSort || FUNC==afInsert || FUNC==afUnshift || FUNC==af__SetSizeExact || FUNC==afBlit)
if (FUNC==afSort || FUNC==afInsert || FUNC==afUnshift || FUNC==af__SetSizeExact || FUNC==afBlit ||
FUNC==afReverse || FUNC==afResize)
{
runVoid(ctx);
return 0;
Expand Down Expand Up @@ -456,6 +465,24 @@ struct ArrayBuiltinAny : public ArrayBuiltinBase
thisVal->__SetSizeExact(size);
return;
}
if (FUNC==afResize)
{
ArrayAnyImpl *thisVal = (ArrayAnyImpl *)thisExpr->runObject(ctx);
BCR_VCHECK;
CPPIA_CHECK(thisVal);
int size = args[0]->runInt(ctx);
BCR_VCHECK;
thisVal->CALL(resize)(size);
return;
}
if (FUNC==afReverse)
{
ArrayAnyImpl *thisVal = (ArrayAnyImpl *)thisExpr->runObject(ctx);
BCR_VCHECK;
CPPIA_CHECK(thisVal);
thisVal->CALL(reverse)();
return;
}
if (FUNC==afBlit)
{
ArrayAnyImpl *thisVal = (ArrayAnyImpl *)thisExpr->runObject(ctx);
Expand Down Expand Up @@ -586,6 +613,8 @@ struct ArrayBuiltinAny : public ArrayBuiltinBase
case afUnshift:
case af__SetSizeExact:
case afBlit:
case afReverse:
case afResize:
return etVoid;

case afPush:
Expand Down Expand Up @@ -623,14 +652,14 @@ struct ArrayBuiltinAny : public ArrayBuiltinBase
return 0;
}

static int SLJIT_CALL runIndexOf( ArrayAnyImpl *inArray, hx::Object *inItem)
static int SLJIT_CALL runIndexOf( ArrayAnyImpl *inArray, hx::Object *inItem, hx::Object *inFrom)
{
return inArray->indexOf(inItem);
return inArray->indexOf(inItem, inFrom);
}

static int SLJIT_CALL runLastIndexOf( ArrayAnyImpl *inArray, hx::Object *inItem)
static int SLJIT_CALL runLastIndexOf( ArrayAnyImpl *inArray, hx::Object *inItem, hx::Object *inFrom)
{
return inArray->lastIndexOf(inItem);
return inArray->lastIndexOf(inItem, inFrom);
}


Expand Down Expand Up @@ -727,8 +756,11 @@ struct ArrayBuiltinAny : public ArrayBuiltinBase
case afIndexOf:
case afLastIndexOf:
{
args[0]->genCode(compiler, sJitArg1.as(jtPointer), etObject);
compiler->callNative( (void *)(FUNC==afIndexOf ? runIndexOf : runLastIndexOf), thisVal, sJitArg1.as(jtPointer));
// The item, then fromIndex, which is null when the call leaves it out
JitTemp item(compiler,etObject);
args[0]->genCode(compiler, item, etObject);
args[1]->genCode(compiler, sJitArg2, etObject);
compiler->callNative( (void *)(FUNC==afIndexOf ? runIndexOf : runLastIndexOf), thisVal, item.as(jtPointer), sJitArg2.as(jtPointer));
compiler->convertReturnReg(etInt, inDest, destType );
}
break;
Expand All @@ -754,23 +786,19 @@ struct ArrayBuiltinAny : public ArrayBuiltinBase
}
break;

// The array is thisVal, evaluated and checked above: evaluating it
// again would run its side effects twice
case af__SetSizeExact:
{
JitTemp thisVal(compiler,jtPointer);
thisExpr->genCode(compiler, thisVal, etObject);
args[0]->genCode(compiler, sJitArg1.as(jtInt), etInt);
compiler->callNative( (void *)arraySetSizeExact, thisVal, sJitArg1.as(jtInt));
break;
}
args[0]->genCode(compiler, sJitArg1.as(jtInt), etInt);
compiler->callNative( (void *)arraySetSizeExact, thisVal, sJitArg1.as(jtInt));
compiler->checkException();
break;

case afResize:
{
JitTemp thisVal(compiler,jtPointer);
thisExpr->genCode(compiler, thisVal, etObject);
args[0]->genCode(compiler, sJitArg1.as(jtInt), etInt);
compiler->callNative( (void *)arrayResize, thisVal, sJitArg1.as(jtInt));
break;
}
args[0]->genCode(compiler, sJitArg1.as(jtInt), etInt);
compiler->callNative( (void *)arrayResize, thisVal, sJitArg1.as(jtInt));
compiler->checkException();
break;

case afBlit:
{
Expand All @@ -784,6 +812,7 @@ struct ArrayBuiltinAny : public ArrayBuiltinBase
args[2]->genCode(compiler, fargs.arg(3,jtInt), etInt);
args[3]->genCode(compiler, fargs.arg(4,jtInt), etInt);
compiler->callNative( (void *)runBlit, fargs );
compiler->checkException();
break;
}

Expand Down
13 changes: 13 additions & 0 deletions test/regression/CppiaArrayHelperExceptions/Main.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Runs the script interpreted and then under the JIT
function main() {
var script = haxe.io.Path.join([haxe.io.Path.directory(Sys.programPath()), "script.cppia"]);
for (jit in [false, true]) {
cpp.cppia.Host.enableJit(jit);
Sys.println(jit ? "jit" : "interpreted");
try {
cpp.cppia.Host.runFile(script);
} catch (e:Dynamic) {
Sys.println("error: " + e);
}
}
}
57 changes: 57 additions & 0 deletions test/regression/CppiaArrayHelperExceptions/Script.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Under the JIT, an exception from blit, setSize or resize called directly in
// a try went past the script's catch and ended the host, on a typed array
// and on Array<Dynamic>. Each one throws here, and the script catches it and
// finds the array as it was. A valid blit is the control.
class Script {
static function main() {
var dest = [7, 8];
var source = [1, 2];
var values = [7, 8];
var anyDest:Array<Dynamic> = [7, "eight"];
var anySource:Array<Dynamic> = [1, "two"];
var any:Array<Dynamic> = [7, "eight"];
try {
cpp.NativeArray.blit(dest, 1, source, 0, 1);
Sys.println("valid blit: ran, " + dest);
} catch (e:Dynamic) {
Sys.println("valid blit: caught " + e + ", " + dest);
}
try {
cpp.NativeArray.blit(dest, -1, source, 0, 1);
Sys.println("blit: ran, " + dest);
} catch (e:Dynamic) {
Sys.println("blit: caught " + e + ", " + dest);
}
try {
cpp.NativeArray.setSize(values, -1);
Sys.println("setSize: ran, " + values);
} catch (e:Dynamic) {
Sys.println("setSize: caught " + e + ", " + values);
}
try {
values.resize(0x40000000);
Sys.println("resize: ran, " + values);
} catch (e:Dynamic) {
Sys.println("resize: caught " + e + ", " + values);
}
try {
cpp.NativeArray.blit(anyDest, -1, anySource, 0, 1);
Sys.println("dynamic blit: ran, " + anyDest);
} catch (e:Dynamic) {
Sys.println("dynamic blit: caught " + e + ", " + anyDest);
}
try {
cpp.NativeArray.setSize(any, -1);
Sys.println("dynamic setSize: ran, " + any);
} catch (e:Dynamic) {
Sys.println("dynamic setSize: caught " + e + ", " + any);
}
try {
any.resize(0x40000000);
Sys.println("dynamic resize: ran, " + any);
} catch (e:Dynamic) {
Sys.println("dynamic resize: caught " + e + ", " + any);
}
Sys.println("continued");
}
}
7 changes: 7 additions & 0 deletions test/regression/CppiaArrayHelperExceptions/build.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
--main Script
-cppia bin/script.cppia
--next
--main Main
-cpp bin
-D scriptable
--dce no
18 changes: 18 additions & 0 deletions test/regression/CppiaArrayHelperExceptions/stdout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
interpreted
valid blit: ran, [7,1]
blit: caught blit out of bounds, [7,1]
setSize: caught Array allocation too large, [7,8]
resize: caught Array allocation too large, [7,8]
dynamic blit: caught blit out of bounds, [7,eight]
dynamic setSize: caught Array allocation too large, [7,eight]
dynamic resize: caught Array allocation too large, [7,eight]
continued
jit
valid blit: ran, [7,1]
blit: caught blit out of bounds, [7,1]
setSize: caught Array allocation too large, [7,8]
resize: caught Array allocation too large, [7,8]
dynamic blit: caught blit out of bounds, [7,eight]
dynamic setSize: caught Array allocation too large, [7,eight]
dynamic resize: caught Array allocation too large, [7,eight]
continued
13 changes: 13 additions & 0 deletions test/regression/CppiaDynamicArrayResizeReceiver/Main.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Runs the script interpreted and then under the JIT
function main() {
var script = haxe.io.Path.join([haxe.io.Path.directory(Sys.programPath()), "script.cppia"]);
for (jit in [false, true]) {
cpp.cppia.Host.enableJit(jit);
Sys.println(jit ? "jit" : "interpreted");
try {
cpp.cppia.Host.runFile(script);
} catch (e:Dynamic) {
Sys.println("error: " + e);
}
}
}
Loading
Loading