Browse Source

Testcase cleanup and improvement for fast returns

pull/345/head
Sami Vaarala 9 years ago
parent
commit
fb3165667b
  1. 159
      tests/api/test-dev-return-types.c
  2. 4
      tests/api/test-dump-load-basic.c
  3. 57
      tests/ecmascript/test-dev-return-cases.js
  4. 2
      tests/perf/test-call-basic.js
  5. 19
      tests/perf/test-call-native.js

159
tests/api/test-dev-return-types.c

@ -0,0 +1,159 @@
/*
* Supporting testcase for test-dev-return-types.js: cover return types
* which can't be exercised from Ecmascript code.
*/
/*===
*** test_basic_implicit (duk_safe_call)
inside func
result: undefined
final top: 0
==> rc=0, result='undefined'
*** test_basic_explicit (duk_safe_call)
inside func
result: 123
final top: 0
==> rc=0, result='undefined'
*** test_endfin_return (duk_safe_call)
finally
result: 321
final top: 0
==> rc=0, result='undefined'
inside func
result: undefined
inside func
result: undefined
inside func
result: 123
inside func
result: 123
finally
result: 321
finally
result: 321
final top: 0
===*/
/* Normal call from a duk_safe_call() wrapper, implicit return value. */
static duk_ret_t test_basic_implicit(duk_context *ctx) {
duk_eval_string(ctx,
"(function () {\n"
" print('inside func');\n"
"})");
duk_call(ctx, 0);
printf("result: %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/* Normal call from a duk_safe_call() wrapper, explicit return value. */
static duk_ret_t test_basic_explicit(duk_context *ctx) {
duk_eval_string(ctx,
"(function () {\n"
" print('inside func');\n"
" return 123;\n"
"})");
duk_call(ctx, 0);
printf("result: %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/* Ecmascript finally captures return and the return is propagated
* onwards after finally finishes.
*/
static duk_ret_t test_endfin_return(duk_context *ctx) {
duk_eval_string(ctx,
"(function () {\n"
" try {\n"
" return 321;\n"
" } finally {\n"
" print('finally');\n"
" }\n"
" print('never here');\n"
"})");
duk_call(ctx, 0);
printf("result: %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
void test(duk_context *ctx) {
TEST_SAFE_CALL(test_basic_implicit);
TEST_SAFE_CALL(test_basic_explicit);
TEST_SAFE_CALL(test_endfin_return);
/* Top level unprotected call + return with implicit value. */
duk_eval_string(ctx,
"(function () {\n"
" print('inside func');\n"
"})");
duk_call(ctx, 0);
printf("result: %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx);
/* Top level protected call + return with explicit value. */
duk_eval_string(ctx,
"(function () {\n"
" print('inside func');\n"
"})");
(void) duk_pcall(ctx, 0);
printf("result: %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx);
/* Top level unprotected call + return with explicit value. */
duk_eval_string(ctx,
"(function () {\n"
" print('inside func');\n"
" return 123;\n"
"})");
duk_call(ctx, 0);
printf("result: %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx);
/* Top level protected call + return with explicit value. */
duk_eval_string(ctx,
"(function () {\n"
" print('inside func');\n"
" return 123;\n"
"})");
duk_pcall(ctx, 0);
printf("result: %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx);
/* ENDFIN + RETURN case directly from top level, unprotected call. */
duk_eval_string(ctx,
"(function () {\n"
" try {\n"
" return 321;\n"
" } finally {\n"
" print('finally');\n"
" }\n"
" print('never here');\n"
"})");
duk_call(ctx, 0);
printf("result: %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx);
/* ENDFIN + RETURN case directly from top level, protected call. */
duk_eval_string(ctx,
"(function () {\n"
" try {\n"
" return 321;\n"
" } finally {\n"
" print('finally');\n"
" }\n"
" print('never here');\n"
"})");
duk_pcall(ctx, 0);
printf("result: %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
}

4
tests/api/test-dump-load-basic.c

@ -40,7 +40,7 @@
/*=== /*===
*** test_basic (duk_safe_call) *** test_basic (duk_safe_call)
dump result type: 7 dump result type: 7
ff000000000e0000000300000001000900000000000100000001300004c0000000f300400052000040c200000114000101400001414c800041c3800082030101403000014100000081420180403000004000000000ef00000000057072696e74000000000568656c6c6f0140091eb851eb851f000000030000000000000000000300020000000100000001300604400080009a000080ef0000006f000000020000000561646465720000000f66616b6546696c656e616d652e6a730000000d03000000010000000c000000000000000178000000000000000179000000010000000000000001780000000179000000000000000000000006676c6f62616c0000000f66616b6546696c656e616d652e6a730000000e0e000000010000000c00000000000000000000000000 ff000000000e0000000300000001000900000000000100000001300004c0000000f300400052000040c200000114000101400001414c800041c38000820301014030000141000000814201804030000040000000006f00000000057072696e74000000000568656c6c6f0140091eb851eb851f000000030000000000000000000300020000000100000001300604400080009a0000806f0000002f000000020000000561646465720000000f66616b6546696c656e616d652e6a730000000d03000000010000000c000000000000000178000000000000000179000000010000000000000001780000000179000000000000000000000006676c6f62616c0000000f66616b6546696c656e616d652e6a730000000e0e000000010000000c00000000000000000000000000
load result type: 6 load result type: 6
hello 3 3.14 hello 3 3.14
call result type: 1 call result type: 1
@ -91,7 +91,7 @@ static duk_ret_t test_basic(duk_context *ctx) {
/*=== /*===
*** test_mandel (duk_safe_call) *** test_mandel (duk_safe_call)
Mandelbrot source length: 884 Mandelbrot source length: 884
ff000000006c000000100000000000140000000000010000001e300604c0801300038007004380190083000008338000196e800001ae80000403000400c00080c3ab0003802d800000ee800017ae0000c3b67ffffeae0080c39d8003839c8083839b00038200000048338000136e8000022e80000403000401000004423300044340000103ab0003802d800000ee8000112e000103b67ffffeae0001039d8103839c8183839b000381c00000883380000d6e8000032e800004030004014080000443000442408000048300048280000104c20004c180010143ab0003802d800000ee80000a2e000143b67ffffeae0482439c000382c00502839c000383000602c39a828383ab0003806d8000022e04c0c39c0503839c0403839a000382800602c39b0383839a000382407ffffbae810143ab0003806d800000ee00018382000381808000042e838143ab0003806d800000ee0002038200038180800002ae848143ab0003806d800000ee00028382000381808000012e0002c382000381808000006e7ffff62e0000887300034380000303c20783839800018400008380307fffef2e00004873004343920003440000038442088404180003c48200840030008380307fffe8ae000008730000006f014004000000000000013ff400000000000001400800000000000001400000000000000000000000012301401000000000000000000000012e01401400000000000000000000012c01402400000000000000000000012d00000000013d00000000047075736800000000057072696e7400000000046a6f696e000000000000000000000000066d616e64656c000000096d616e64656c2e6a730000002a6c00000002000000140000000f0000002000000028801004002008000409100022420100822501080210000000017700000000000000016800000001000000046974657200000002000000016900000003000000016a00000004000000016b000000050000000163000000060000000278300000000700000002793000000008000000027878000000090000000279790000000a000000037878320000000b000000037979320000000c000000046c696e650000000d0000000000000000 ff000000006c000000100000000000140000000000010000001e300604c0801300038007004380190083000008338000196e800001ae80000403000400c00080c3ab0003802d800000ee800017ae0000c3b67ffffeae0080c39d8003839c8083839b00038200000048338000136e8000022e80000403000401000004423300044340000103ab0003802d800000ee8000112e000103b67ffffeae0001039d8103839c8183839b000381c00000883380000d6e8000032e800004030004014080000443000442408000048300048280000104c20004c180010143ab0003802d800000ee80000a2e000143b67ffffeae0482439c000382c00502839c000383000602c39a828383ab0003806d8000022e04c0c39c0503839c0403839a000382800602c39b0383839a000382407ffffbae810143ab0003806d800000ee00018382000381808000042e838143ab0003806d800000ee0002038200038180800002ae848143ab0003806d800000ee00028382000381808000012e0002c382000381808000006e7ffff62e0000887300034380000303c20783839800018400008380307fffef2e00004873004343920003440000038442088404180003c48200840030008380307fffe8ae000008730000002f014004000000000000013ff400000000000001400800000000000001400000000000000000000000012301401000000000000000000000012e01401400000000000000000000012c01402400000000000000000000012d00000000013d00000000047075736800000000057072696e7400000000046a6f696e000000000000000000000000066d616e64656c000000096d616e64656c2e6a730000002a6c00000002000000140000000f0000002000000028801004002008000409100022420100822501080210000000017700000000000000016800000001000000046974657200000002000000016900000003000000016a00000004000000016b000000050000000163000000060000000278300000000700000002793000000008000000027878000000090000000279790000000a000000037878320000000b000000037979320000000c000000046c696e650000000d0000000000000000
..........................,,,,,,,,,,,,,,,,,,,,,,,,,......................... ..........................,,,,,,,,,,,,,,,,,,,,,,,,,.........................
....................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,................... ....................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,...................
................,,,,,,,,,,,,,,,,,,,,,,,,,,,---=----,,,,,,,,,,............... ................,,,,,,,,,,,,,,,,,,,,,,,,,,,---=----,,,,,,,,,,...............

57
tests/ecmascript/test-dev-fast-return-cases.js → tests/ecmascript/test-dev-return-cases.js

@ -1,17 +1,5 @@
/* /*
* Exercise various code paths related to fast return handling. * Exercise various code paths related to return handling.
*
* Duktape executor supports two kinds of return:
*
* - A slow return is implemented using longjmp() and handles all cases
* like label catchers, try-catch-finally blocks, etc.
*
* - A fast return avoids the longjmp() but is limited to common cases
* only.
*
* Longjmp has a moderate performance impact on normal platforms. However
* it has a much larger relative impact when Duktape is compiled with
* Emscripten.
*/ */
/*=== /*===
@ -39,26 +27,27 @@ testTryFinally4
Error: canceled return Error: canceled return
still here still here
returned 432 returned 432
testTryFinally5
finally
returned 123
===*/ ===*/
/* Basic case: fast return allowed. */ /* Basic case. */
function testReturn1() { function testReturn1() {
return 123; return 123;
} }
/* Basic case, implicit return value (undefined). Fast return allowed. */ /* Basic case, implicit return value (undefined). */
function testReturn2() { function testReturn2() {
return; return;
} }
/* Basic case, implicit return value with no explicit return statement. /* Basic case, implicit return value with no explicit return statement.
* Fast return allowed.
*/ */
function testReturn3() { function testReturn3() {
} }
/* Return from inside a label site (created by for-loop). Fast return /* Return from inside a label site (created by for-loop).
* is allowed for label catchers.
*/ */
function testForLoop1() { function testForLoop1() {
for (;;) { for (;;) {
@ -66,9 +55,7 @@ function testForLoop1() {
} }
} }
/* Return from inside the try block of a try-catch is currently not a /* Return from inside the try block of a try-catch.
* fast return.
* XXX: could allow if there's no finally clause?
*/ */
function testTryCatch1() { function testTryCatch1() {
try { try {
@ -77,9 +64,7 @@ function testTryCatch1() {
} }
} }
/* Return from inside the catch block of a try-catch is currently not a /* Return from inside the catch block of a try-catch.
* fast return.
* XXX: could allow if there's no finally clause?
*/ */
function testTryCatch2() { function testTryCatch2() {
try { try {
@ -89,9 +74,7 @@ function testTryCatch2() {
} }
} }
/* Return from inside the try block of a try-finally is not a fast /* Return from inside the try block of a try-finally.
* return because the finally block intercepts the return (and can
* even cancel it).
*/ */
function testTryFinally1() { function testTryFinally1() {
try { try {
@ -110,10 +93,7 @@ function testTryFinally2() {
} }
} }
/* Return from inside the finally block of a try-finally is not a fast /* Return from inside the finally block of a try-finally.
* return.
* XXX: it could be, because there's no longer a chance of anyone
* catching the return.
*/ */
function testTryFinally3() { function testTryFinally3() {
try { try {
@ -141,6 +121,18 @@ function testTryFinally4() {
return 432; return 432;
} }
function testTryFinally5() {
// Here 'finally' captures the return which then proceeds.
// This triggers the internal case where ENDFIN does RETURN handling
// which results in an executor restart.
try {
return 123;
} finally {
print('finally');
}
print('never here');
}
try { try {
print('testReturn1'); print('testReturn1');
print('returned', testReturn1()); print('returned', testReturn1());
@ -171,6 +163,9 @@ try {
print('testTryFinally4'); print('testTryFinally4');
print('returned', testTryFinally4()); print('returned', testTryFinally4());
print('testTryFinally5');
print('returned', testTryFinally5());
} catch (e) { } catch (e) {
print(e); print(e);
} }

2
tests/perf/test-call-basic.js

@ -1,7 +1,5 @@
/* /*
* Basic function call performance. * Basic function call performance.
*
* Focuses on the cases where "fast returns" are possible.
*/ */
function test() { function test() {

19
tests/perf/test-call-native.js

@ -0,0 +1,19 @@
function test() {
var arr = [];
for (var i = 0; i < 1e3; i++) {
arr[i] = i;
}
for (var i = 0; i < 3e4; i++) {
// Each .forEach() call is a native call so that return 123 causes a
// return-to-native situation which was previously a longjmp.
arr.forEach(function () { return 123; });
}
}
try {
test();
} catch (e) {
print(e.stack || e);
throw e;
}
Loading…
Cancel
Save