diff --git a/src/compiler.ts b/src/compiler.ts index c3c3778a05..d8ee0cdf74 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -8136,7 +8136,8 @@ export class Compiler extends DiagnosticEmitter { var parts = expression.parts; var numParts = parts.length; var expressions = expression.expressions; - assert(numParts - 1 == expressions.length); + var numExpressions = expressions.length; + assert(numExpressions == numParts - 1); var module = this.module; var stringInstance = this.program.stringInstance; @@ -8202,8 +8203,8 @@ export class Compiler extends DiagnosticEmitter { return this.makeCallDirect(concatMethod, [ lhs, rhs ], expression); } - // Compile to a `StaticArray#join("") for general case - let length = 2 * numParts - 1; + // Compile to a `StaticArray#join("") in the general case + let length = numParts + numExpressions; let values = new Array(length); values[0] = this.ensureStaticString(parts[0]); for (let i = 1; i < numParts; ++i) { @@ -8215,19 +8216,33 @@ export class Compiler extends DiagnosticEmitter { let offset = i64_add(segment.offset, i64_new(this.program.totalOverhead)); let joinInstance = assert(arrayInstance.getMethod("join")); let indexedSetInstance = assert(arrayInstance.lookupOverload(OperatorKind.INDEXED_SET, true)); - let stmts = new Array(numParts); - for (let i = 0, k = numParts - 1; i < k; ++i) { + let stmts = new Array(2 * numExpressions + 1); + // Use one local per toString'ed subexpression, since otherwise recursion on the same + // static array would overwrite already prepared parts. Avoids a temporary array. + let temps = new Array(numExpressions); + let flow = this.currentFlow; + for (let i = 0; i < numExpressions; ++i) { let expression = expressions[i]; - stmts[i] = this.makeCallDirect(indexedSetInstance, [ - module.usize(offset), - module.i32(2 * i + 1), + let temp = flow.getTempLocal(stringType); + temps[i] = temp; + stmts[i] = module.local_set(temp.index, this.makeToString( this.compileExpression(expression, stringType), this.currentType, expression - ) + ), + true + ); + } + // Populate the static array with the toString'ed subexpressions and call .join("") + for (let i = 0; i < numExpressions; ++i) { + stmts[numExpressions + i] = this.makeCallDirect(indexedSetInstance, [ + module.usize(offset), + module.i32(2 * i + 1), + module.local_get(temps[i].index, stringType.toRef()) ], expression); + flow.freeTempLocal(temps[i]); } - stmts[numParts - 1] = this.makeCallDirect(joinInstance, [ + stmts[2 * numExpressions] = this.makeCallDirect(joinInstance, [ module.usize(offset), this.ensureStaticString("") ], expression); @@ -8385,19 +8400,7 @@ export class Compiler extends DiagnosticEmitter { // otherwise allocate a new array header and make it wrap a copy of the static buffer } else { - // __newArray(length, alignLog2, classId, staticBuffer) - let expr = this.makeCallDirect(program.newArrayInstance, [ - module.i32(length), - program.options.isWasm64 - ? module.i64(elementType.alignLog2) - : module.i32(elementType.alignLog2), - module.i32(arrayInstance.id), - program.options.isWasm64 - ? module.i64(i64_low(bufferAddress), i64_high(bufferAddress)) - : module.i32(i64_low(bufferAddress)) - ], expression); - this.currentType = arrayType; - return expr; + return this.makeNewArray(arrayInstance, length, bufferAddress, expression); } } @@ -8419,16 +8422,7 @@ export class Compiler extends DiagnosticEmitter { // tempThis = __newArray(length, alignLog2, classId, source = 0) stmts.push( module.local_set(tempThis.index, - this.makeCallDirect(program.newArrayInstance, [ - module.i32(length), - program.options.isWasm64 - ? module.i64(elementType.alignLog2) - : module.i32(elementType.alignLog2), - module.i32(arrayInstance.id), - program.options.isWasm64 - ? module.i64(0) - : module.i32(0) - ], expression), + this.makeNewArray(arrayInstance, length, i64_new(0), expression), arrayType.isManaged ) ); @@ -8466,6 +8460,37 @@ export class Compiler extends DiagnosticEmitter { return module.flatten(stmts, arrayTypeRef); } + /** Makes a new array instance from a static buffer segment. */ + private makeNewArray( + /** Concrete array class. */ + arrayInstance: Class, + /** Length of the array. */ + length: i32, + /** Source address to copy from. Array is zeroed if `0`. */ + source: i64, + /** Report node. */ + reportNode: Node + ): ExpressionRef { + var program = this.program; + var module = this.module; + assert(!arrayInstance.extends(program.staticArrayPrototype)); + var elementType = arrayInstance.getArrayValueType(); // asserts + + // __newArray(length, alignLog2, classId, staticBuffer) + var expr = this.makeCallDirect(program.newArrayInstance, [ + module.i32(length), + program.options.isWasm64 + ? module.i64(elementType.alignLog2) + : module.i32(elementType.alignLog2), + module.i32(arrayInstance.id), + program.options.isWasm64 + ? module.i64(i64_low(source), i64_high(source)) + : module.i32(i64_low(source)) + ], reportNode); + this.currentType = arrayInstance.type; + return expr; + } + /** Compiles a special `fixed` array literal. */ private compileStaticArrayLiteral( expression: ArrayLiteralExpression, diff --git a/tests/compiler/templateliteral.optimized.wat b/tests/compiler/templateliteral.optimized.wat index b91240868a..44041fd406 100644 --- a/tests/compiler/templateliteral.optimized.wat +++ b/tests/compiler/templateliteral.optimized.wat @@ -1,8 +1,8 @@ (module - (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $none_=>_none (func)) + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_none (func (param i32 i32))) (type $f64_=>_i32 (func (param f64) (result i32))) @@ -27,7 +27,7 @@ (global $~lib/util/number/_K (mut i32) (i32.const 0)) (global $~lib/util/number/_frc_pow (mut i64) (i64.const 0)) (global $~lib/util/number/_exp_pow (mut i32) (i32.const 0)) - (global $~lib/memory/__stack_pointer (mut i32) (i32.const 21964)) + (global $~lib/memory/__stack_pointer (mut i32) (i32.const 22116)) (global $~started (mut i32) (i32.const 0)) (memory $0 1) (data (i32.const 1036) "\1c") @@ -124,8 +124,16 @@ (data (i32.const 5432) "\03\00\00\00\14\00\00\00p\06\00\00\00\00\00\00\90\06\00\00\00\00\00\00\b0\06") (data (i32.const 5468) "<") (data (i32.const 5480) "\01\00\00\00$\00\00\00(\00A\00=\00r\00e\00f\00#\001\00,\00 \00B\00=\00r\00e\00f\00#\002\00)") - (data (i32.const 5536) "\05\00\00\00 \00\00\00\00\00\00\00 ") - (data (i32.const 5564) "\04A\00\00\00\00\00\00 ") + (data (i32.const 5532) "\1c") + (data (i32.const 5544) "\01\00\00\00\02\00\00\00c") + (data (i32.const 5564) "\1c") + (data (i32.const 5576) "\01\00\00\00\02\00\00\00:") + (data (i32.const 5596) ",") + (data (i32.const 5608) "\03\00\00\00\14\00\00\00\a0\04\00\00\00\00\00\00\d0\15\00\00\00\00\00\00\a0\04") + (data (i32.const 5644) "\1c") + (data (i32.const 5656) "\01\00\00\00\n\00\00\00a\00:\00b\00:\00c") + (data (i32.const 5680) "\06\00\00\00 \00\00\00\00\00\00\00 ") + (data (i32.const 5708) "\04A\00\00\00\00\00\00 ") (export "memory" (memory $0)) (export "_start" (func $~start)) (func $~lib/string/String.__eq (param $0 i32) (param $1 i32) (result i32) @@ -326,7 +334,7 @@ if i32.const 0 local.get $0 - i32.const 21964 + i32.const 22116 i32.lt_u local.get $0 i32.load offset=8 @@ -376,7 +384,7 @@ if (result i32) i32.const 1 else - i32.const 5536 + i32.const 5680 i32.load local.get $1 i32.lt_u @@ -391,7 +399,7 @@ local.get $1 i32.const 3 i32.shl - i32.const 5540 + i32.const 5684 i32.add i32.load i32.const 32 @@ -987,10 +995,10 @@ if unreachable end - i32.const 21968 + i32.const 22128 i32.const 0 i32.store - i32.const 23536 + i32.const 23696 i32.const 0 i32.store loop $for-loop|0 @@ -1001,7 +1009,7 @@ local.get $1 i32.const 2 i32.shl - i32.const 21968 + i32.const 22128 i32.add i32.const 0 i32.store offset=4 @@ -1019,7 +1027,7 @@ i32.add i32.const 2 i32.shl - i32.const 21968 + i32.const 22128 i32.add i32.const 0 i32.store offset=96 @@ -1037,13 +1045,13 @@ br $for-loop|0 end end - i32.const 21968 - i32.const 23540 + i32.const 22128 + i32.const 23700 memory.size i32.const 16 i32.shl call $~lib/rt/tlsf/addMemory - i32.const 21968 + i32.const 22128 global.set $~lib/rt/tlsf/ROOT ) (func $~lib/rt/itcms/step (result i32) @@ -1127,7 +1135,7 @@ local.set $0 loop $while-continue|0 local.get $0 - i32.const 21964 + i32.const 22116 i32.lt_u if local.get $0 @@ -1222,7 +1230,7 @@ unreachable end local.get $0 - i32.const 21964 + i32.const 22116 i32.lt_u if local.get $0 @@ -1245,7 +1253,7 @@ i32.const 4 i32.add local.tee $0 - i32.const 21964 + i32.const 22116 i32.ge_u if global.get $~lib/rt/tlsf/ROOT @@ -2821,63 +2829,62 @@ end end ) - (func $~lib/staticarray/StaticArray<~lib/string/String>#__uset (param $0 i32) (param $1 i32) (param $2 i32) + (func $~lib/rt/itcms/__link (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) local.get $1 - i32.const 2 - i32.shl + i32.eqz + if + return + end local.get $0 - i32.add - local.get $2 - i32.store - local.get $2 + i32.eqz + if + i32.const 0 + i32.const 1280 + i32.const 294 + i32.const 14 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/rt/itcms/white + local.get $1 + i32.const 20 + i32.sub + local.tee $1 + i32.load offset=4 + i32.const 3 + i32.and + i32.eq if local.get $0 - i32.eqz - if - i32.const 0 - i32.const 1280 - i32.const 294 - i32.const 14 - call $~lib/builtins/abort - unreachable - end - global.get $~lib/rt/itcms/white - local.get $2 i32.const 20 i32.sub - local.tee $2 + local.tee $0 i32.load offset=4 i32.const 3 i32.and + local.tee $3 + global.get $~lib/rt/itcms/white + i32.eqz i32.eq if local.get $0 - i32.const 20 - i32.sub - local.tee $1 - i32.load offset=4 + local.get $1 + local.get $2 + select + call $~lib/rt/itcms/Object#makeGray + else + global.get $~lib/rt/itcms/state + i32.const 1 + i32.eq + i32.const 0 + local.get $3 i32.const 3 - i32.and - local.tee $0 - global.get $~lib/rt/itcms/white - i32.eqz i32.eq + select if local.get $1 call $~lib/rt/itcms/Object#makeGray - else - global.get $~lib/rt/itcms/state - i32.const 1 - i32.eq - i32.const 0 - local.get $0 - i32.const 3 - i32.eq - select - if - local.get $2 - call $~lib/rt/itcms/Object#makeGray - end end end end @@ -2901,11 +2908,11 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 5580 + i32.const 5732 i32.lt_s if - i32.const 21984 - i32.const 22032 + i32.const 22144 + i32.const 22192 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -3213,11 +3220,11 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 5580 + i32.const 5732 i32.lt_s if - i32.const 21984 - i32.const 22032 + i32.const 22144 + i32.const 22192 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -4382,11 +4389,11 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 5580 + i32.const 5732 i32.lt_s if - i32.const 21984 - i32.const 22032 + i32.const 22144 + i32.const 22192 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -4469,7 +4476,7 @@ memory.size i32.const 16 i32.shl - i32.const 21964 + i32.const 22116 i32.sub i32.const 1 i32.shr_u @@ -4502,11 +4509,11 @@ i32.const 24 i32.sub global.set $~lib/memory/__stack_pointer - block $folding-inner0 + block $folding-inner1 global.get $~lib/memory/__stack_pointer - i32.const 5580 + i32.const 5732 i32.lt_s - br_if $folding-inner0 + br_if $folding-inner1 global.get $~lib/memory/__stack_pointer local.tee $0 i64.const 0 @@ -4564,21 +4571,28 @@ global.get $~lib/memory/__stack_pointer i32.const 1744 i32.store offset=16 + i32.const 1748 + i32.const 1056 + i32.store i32.const 1744 - i32.const 1 i32.const 1056 - call $~lib/staticarray/StaticArray<~lib/string/String>#__uset + i32.const 1 + call $~lib/rt/itcms/__link global.get $~lib/memory/__stack_pointer i32.const 1744 i32.store offset=16 + i32.const 1756 + i32.const 1088 + i32.store i32.const 1744 - i32.const 3 i32.const 1088 - call $~lib/staticarray/StaticArray<~lib/string/String>#__uset + i32.const 1 + call $~lib/rt/itcms/__link global.get $~lib/memory/__stack_pointer + local.tee $0 i32.const 1744 i32.store offset=16 - global.get $~lib/memory/__stack_pointer + local.get $0 i32.const 1184 i32.store offset=20 i32.const 1744 @@ -4607,13 +4621,13 @@ i32.add global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 20 + i32.const 24 i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 5580 + i32.const 5732 i32.lt_s - br_if $folding-inner0 + br_if $folding-inner1 global.get $~lib/memory/__stack_pointer local.tee $0 i64.const 0 @@ -4622,8 +4636,8 @@ i64.const 0 i64.store offset=8 local.get $0 - i32.const 0 - i32.store offset=16 + i64.const 0 + i64.store offset=16 i32.const 1 call $~lib/number/I32#toString local.set $0 @@ -4680,35 +4694,40 @@ unreachable end global.get $~lib/memory/__stack_pointer - i32.const 3680 - i32.store offset=8 i32.const 1 call $~lib/number/I32#toString - local.set $0 - global.get $~lib/memory/__stack_pointer - local.get $0 + local.tee $0 i32.store offset=16 - i32.const 3680 - i32.const 1 - local.get $0 - call $~lib/staticarray/StaticArray<~lib/string/String>#__uset global.get $~lib/memory/__stack_pointer - i32.const 3680 - i32.store offset=8 i32.const 2 call $~lib/number/I32#toString - local.set $0 + local.tee $1 + i32.store offset=20 global.get $~lib/memory/__stack_pointer + i32.const 3680 + i32.store offset=8 + i32.const 3684 local.get $0 - i32.store offset=16 + i32.store i32.const 3680 - i32.const 3 local.get $0 - call $~lib/staticarray/StaticArray<~lib/string/String>#__uset + i32.const 1 + call $~lib/rt/itcms/__link global.get $~lib/memory/__stack_pointer i32.const 3680 i32.store offset=8 + i32.const 3692 + local.get $1 + i32.store + i32.const 3680 + local.get $1 + i32.const 1 + call $~lib/rt/itcms/__link global.get $~lib/memory/__stack_pointer + local.tee $0 + i32.const 3680 + i32.store offset=8 + local.get $0 i32.const 1184 i32.store offset=12 i32.const 3680 @@ -4733,17 +4752,17 @@ unreachable end global.get $~lib/memory/__stack_pointer - i32.const 20 + i32.const 24 i32.add global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 20 + i32.const 24 i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 5580 + i32.const 5732 i32.lt_s - br_if $folding-inner0 + br_if $folding-inner1 global.get $~lib/memory/__stack_pointer local.tee $0 i64.const 0 @@ -4752,8 +4771,8 @@ i64.const 0 i64.store offset=8 local.get $0 - i32.const 0 - i32.store offset=16 + i64.const 0 + i64.store offset=16 f64.const 1 call $~lib/number/F64#toString local.set $0 @@ -4810,35 +4829,40 @@ unreachable end global.get $~lib/memory/__stack_pointer - i32.const 4976 - i32.store offset=8 f64.const 1 call $~lib/number/F64#toString - local.set $0 - global.get $~lib/memory/__stack_pointer - local.get $0 + local.tee $0 i32.store offset=16 - i32.const 4976 - i32.const 1 - local.get $0 - call $~lib/staticarray/StaticArray<~lib/string/String>#__uset global.get $~lib/memory/__stack_pointer - i32.const 4976 - i32.store offset=8 f64.const 2 call $~lib/number/F64#toString - local.set $0 + local.tee $1 + i32.store offset=20 global.get $~lib/memory/__stack_pointer + i32.const 4976 + i32.store offset=8 + i32.const 4980 local.get $0 - i32.store offset=16 + i32.store i32.const 4976 - i32.const 3 local.get $0 - call $~lib/staticarray/StaticArray<~lib/string/String>#__uset + i32.const 1 + call $~lib/rt/itcms/__link global.get $~lib/memory/__stack_pointer i32.const 4976 i32.store offset=8 + i32.const 4988 + local.get $1 + i32.store + i32.const 4976 + local.get $1 + i32.const 1 + call $~lib/rt/itcms/__link global.get $~lib/memory/__stack_pointer + local.tee $0 + i32.const 4976 + i32.store offset=8 + local.get $0 i32.const 1184 i32.store offset=12 i32.const 4976 @@ -4863,7 +4887,7 @@ unreachable end global.get $~lib/memory/__stack_pointer - i32.const 20 + i32.const 24 i32.add global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer @@ -4871,9 +4895,9 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 5580 + i32.const 5732 i32.lt_s - br_if $folding-inner0 + br_if $folding-inner1 global.get $~lib/memory/__stack_pointer local.tee $0 i64.const 0 @@ -5069,13 +5093,13 @@ i32.add global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 28 + i32.const 32 i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 5580 + i32.const 5732 i32.lt_s - br_if $folding-inner0 + br_if $folding-inner1 global.get $~lib/memory/__stack_pointer local.tee $0 i64.const 0 @@ -5087,8 +5111,8 @@ i64.const 0 i64.store offset=16 local.get $0 - i32.const 0 - i32.store offset=24 + i64.const 0 + i64.store offset=24 local.get $0 i32.const 1 call $templateliteral/Ref#constructor @@ -5155,35 +5179,40 @@ unreachable end global.get $~lib/memory/__stack_pointer - i32.const 5440 - i32.store offset=16 local.get $0 call $templateliteral/Ref#toString - local.set $0 - global.get $~lib/memory/__stack_pointer - local.get $0 + local.tee $0 i32.store offset=24 - i32.const 5440 - i32.const 1 - local.get $0 - call $~lib/staticarray/StaticArray<~lib/string/String>#__uset global.get $~lib/memory/__stack_pointer - i32.const 5440 - i32.store offset=16 local.get $1 call $templateliteral/Ref#toString - local.set $0 + local.tee $1 + i32.store offset=28 global.get $~lib/memory/__stack_pointer + i32.const 5440 + i32.store offset=16 + i32.const 5444 local.get $0 - i32.store offset=24 + i32.store i32.const 5440 - i32.const 3 local.get $0 - call $~lib/staticarray/StaticArray<~lib/string/String>#__uset + i32.const 1 + call $~lib/rt/itcms/__link global.get $~lib/memory/__stack_pointer i32.const 5440 i32.store offset=16 + i32.const 5452 + local.get $1 + i32.store + i32.const 5440 + local.get $1 + i32.const 1 + call $~lib/rt/itcms/__link global.get $~lib/memory/__stack_pointer + local.tee $0 + i32.const 5440 + i32.store offset=16 + local.get $0 i32.const 1184 i32.store offset=20 i32.const 5440 @@ -5208,13 +5237,83 @@ unreachable end global.get $~lib/memory/__stack_pointer - i32.const 28 + i32.const 32 + i32.add + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 20 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 5732 + i32.lt_s + br_if $folding-inner1 + global.get $~lib/memory/__stack_pointer + local.tee $0 + i64.const 0 + i64.store + local.get $0 + i64.const 0 + i64.store offset=8 + local.get $0 + i32.const 0 + i32.store offset=16 + local.get $0 + i32.const 5552 + i32.store + local.get $0 + i32.const 5552 + i32.const 0 + call $templateliteral/RecursiveObject#constructor + local.tee $0 + i32.store offset=4 + global.get $~lib/memory/__stack_pointer + i32.const 1088 + i32.store + global.get $~lib/memory/__stack_pointer + i32.const 1088 + local.get $0 + call $templateliteral/RecursiveObject#constructor + local.tee $0 + i32.store offset=8 + global.get $~lib/memory/__stack_pointer + i32.const 1056 + i32.store + global.get $~lib/memory/__stack_pointer + i32.const 1056 + local.get $0 + call $templateliteral/RecursiveObject#constructor + local.tee $0 + i32.store offset=12 + local.get $0 + call $templateliteral/RecursiveObject#toString + local.set $0 + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store offset=16 + global.get $~lib/memory/__stack_pointer + i32.const 5664 + i32.store + local.get $0 + i32.const 5664 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 118 + i32.const 3 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + i32.const 20 i32.add global.set $~lib/memory/__stack_pointer return end - i32.const 21984 - i32.const 22032 + i32.const 22144 + i32.const 22192 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -5224,58 +5323,77 @@ (local $1 i32) (local $2 i32) block $invalid - block $templateliteral/Ref - block $~lib/staticarray/StaticArray<~lib/string/String> - block $~lib/arraybuffer/ArrayBufferView - block $~lib/string/String - block $~lib/arraybuffer/ArrayBuffer - local.get $0 - i32.const 8 - i32.sub - i32.load - br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $~lib/staticarray/StaticArray<~lib/string/String> $templateliteral/Ref $invalid + block $templateliteral/RecursiveObject + block $templateliteral/Ref + block $~lib/staticarray/StaticArray<~lib/string/String> + block $~lib/arraybuffer/ArrayBufferView + block $~lib/string/String + block $~lib/arraybuffer/ArrayBuffer + local.get $0 + i32.const 8 + i32.sub + i32.load + br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $~lib/staticarray/StaticArray<~lib/string/String> $templateliteral/Ref $templateliteral/RecursiveObject $invalid + end + return end return end + local.get $0 + i32.load + local.tee $0 + if + local.get $0 + call $~lib/rt/itcms/__visit + end return end local.get $0 - i32.load - local.tee $0 - if - local.get $0 - call $~lib/rt/itcms/__visit - end - return - end - local.get $0 - i32.const 20 - i32.sub - i32.load offset=16 - local.get $0 - i32.add - local.set $1 - loop $while-continue|0 + local.tee $1 local.get $0 - local.get $1 - i32.lt_u - if - local.get $0 - i32.load - local.tee $2 + i32.const 20 + i32.sub + i32.load offset=16 + i32.add + local.set $2 + loop $while-continue|0 + local.get $1 + local.get $2 + i32.lt_u if - local.get $2 - call $~lib/rt/itcms/__visit + local.get $1 + i32.load + local.tee $0 + if + local.get $0 + call $~lib/rt/itcms/__visit + end + local.get $1 + i32.const 4 + i32.add + local.set $1 + br $while-continue|0 end - local.get $0 - i32.const 4 - i32.add - local.set $0 - br $while-continue|0 end + return end return end + local.get $0 + local.tee $1 + i32.load + local.tee $0 + if + local.get $0 + call $~lib/rt/itcms/__visit + end + local.get $1 + i32.load offset=4 + local.tee $1 + if + local.get $1 + call $~lib/rt/itcms/__visit + end return end unreachable @@ -5296,11 +5414,11 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 5580 + i32.const 5732 i32.lt_s if - i32.const 21984 - i32.const 22032 + i32.const 22144 + i32.const 22192 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -5328,6 +5446,95 @@ i32.add global.set $~lib/memory/__stack_pointer ) + (func $templateliteral/RecursiveObject#toString (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 20 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 5732 + i32.lt_s + if + i32.const 22144 + i32.const 22192 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.tee $1 + i64.const 0 + i64.store + local.get $1 + i64.const 0 + i64.store offset=8 + local.get $1 + i32.const 0 + i32.store offset=16 + local.get $1 + local.get $0 + i32.load offset=4 + local.tee $1 + i32.store + local.get $1 + i32.eqz + if + local.get $0 + i32.load + global.get $~lib/memory/__stack_pointer + i32.const 20 + i32.add + global.set $~lib/memory/__stack_pointer + return + end + global.get $~lib/memory/__stack_pointer + local.tee $2 + local.get $0 + i32.load + local.tee $0 + i32.store offset=4 + local.get $2 + local.get $1 + call $templateliteral/RecursiveObject#toString + local.tee $1 + i32.store offset=8 + global.get $~lib/memory/__stack_pointer + i32.const 5616 + i32.store offset=12 + i32.const 5620 + local.get $0 + i32.store + i32.const 5616 + local.get $0 + i32.const 1 + call $~lib/rt/itcms/__link + global.get $~lib/memory/__stack_pointer + i32.const 5616 + i32.store offset=12 + i32.const 5628 + local.get $1 + i32.store + i32.const 5616 + local.get $1 + i32.const 1 + call $~lib/rt/itcms/__link + global.get $~lib/memory/__stack_pointer + local.tee $0 + i32.const 5616 + i32.store offset=12 + local.get $0 + i32.const 1184 + i32.store offset=16 + i32.const 5616 + call $~lib/staticarray/StaticArray<~lib/string/String>#join + global.get $~lib/memory/__stack_pointer + i32.const 20 + i32.add + global.set $~lib/memory/__stack_pointer + ) (func $~lib/string/String#concat (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) @@ -5337,11 +5544,11 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 5580 + i32.const 5732 i32.lt_s if - i32.const 21984 - i32.const 22032 + i32.const 22144 + i32.const 22192 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -5408,11 +5615,11 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 5580 + i32.const 5732 i32.lt_s if - i32.const 21984 - i32.const 22032 + i32.const 22144 + i32.const 22192 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -5437,4 +5644,51 @@ global.set $~lib/memory/__stack_pointer local.get $1 ) + (func $templateliteral/RecursiveObject#constructor (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 5732 + i32.lt_s + if + i32.const 22144 + i32.const 22192 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.tee $2 + i32.const 0 + i32.store + local.get $2 + i32.const 8 + i32.const 5 + call $~lib/rt/itcms/__new + local.tee $2 + i32.store + local.get $2 + local.get $0 + i32.store + local.get $2 + local.get $0 + i32.const 0 + call $~lib/rt/itcms/__link + local.get $2 + local.get $1 + i32.store offset=4 + local.get $2 + local.get $1 + i32.const 0 + call $~lib/rt/itcms/__link + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $2 + ) ) diff --git a/tests/compiler/templateliteral.ts b/tests/compiler/templateliteral.ts index c015573c32..b6d3782712 100644 --- a/tests/compiler/templateliteral.ts +++ b/tests/compiler/templateliteral.ts @@ -96,3 +96,25 @@ function test_raw(): void { assert(raw`\u1000` == "\\u1000"); } // test_raw(); // TODO: Requires ReadonlyArray to be safe + +class RecursiveObject { + constructor( + public key: string, + public val: RecursiveObject | null = null + ) {} + toString(): string { + let val = this.val; + if (!val) return this.key; + // see: https://github.com/AssemblyScript/assemblyscript/issues/1944 + // trigger general case by wrapping three times below (2x with value) + return `${this.key}:${val}`; + } +} + +function test_recursive(): void { + const c = new RecursiveObject("c"); + const b = new RecursiveObject("b", c); + const a = new RecursiveObject("a", b); + assert(a.toString() == "a:b:c"); +} +test_recursive(); diff --git a/tests/compiler/templateliteral.untouched.wat b/tests/compiler/templateliteral.untouched.wat index 9b05fd6b6b..324a967b2c 100644 --- a/tests/compiler/templateliteral.untouched.wat +++ b/tests/compiler/templateliteral.untouched.wat @@ -1,8 +1,8 @@ (module (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_=>_i32 (func (param i32) (result i32))) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $none_=>_none (func)) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $i32_=>_none (func (param i32))) (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) @@ -35,10 +35,10 @@ (global $~lib/util/number/_K (mut i32) (i32.const 0)) (global $~lib/util/number/_frc_pow (mut i64) (i64.const 0)) (global $~lib/util/number/_exp_pow (mut i32) (i32.const 0)) - (global $~lib/rt/__rtti_base i32 (i32.const 4512)) - (global $~lib/memory/__data_end i32 (i32.const 4556)) - (global $~lib/memory/__stack_pointer (mut i32) (i32.const 20940)) - (global $~lib/memory/__heap_base i32 (i32.const 20940)) + (global $~lib/rt/__rtti_base i32 (i32.const 4656)) + (global $~lib/memory/__data_end i32 (i32.const 4708)) + (global $~lib/memory/__stack_pointer (mut i32) (i32.const 21092)) + (global $~lib/memory/__heap_base i32 (i32.const 21092)) (global $~started (mut i32) (i32.const 0)) (memory $0 1) (data (i32.const 12) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00a\00\00\00\00\00\00\00\00\00\00\00") @@ -94,7 +94,11 @@ (data (i32.const 4348) ",\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\14\00\00\00r\00e\00f\00#\001\00r\00e\00f\00#\002\00\00\00\00\00\00\00\00\00") (data (i32.const 4396) ",\00\00\00\00\00\00\00\00\00\00\00\03\00\00\00\14\00\00\00p\02\00\00\00\00\00\00\90\02\00\00\00\00\00\00\b0\02\00\00\00\00\00\00\00\00\00\00") (data (i32.const 4444) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00$\00\00\00(\00A\00=\00r\00e\00f\00#\001\00,\00 \00B\00=\00r\00e\00f\00#\002\00)\00\00\00\00\00\00\00\00\00") - (data (i32.const 4512) "\05\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\04A\00\00\00\00\00\00 \00\00\00\00\00\00\00") + (data (i32.const 4508) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00c\00\00\00\00\00\00\00\00\00\00\00") + (data (i32.const 4540) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00:\00\00\00\00\00\00\00\00\00\00\00") + (data (i32.const 4572) ",\00\00\00\00\00\00\00\00\00\00\00\03\00\00\00\14\00\00\00\a0\00\00\00\00\00\00\00\d0\11\00\00\00\00\00\00\a0\00\00\00\00\00\00\00\00\00\00\00") + (data (i32.const 4620) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\n\00\00\00a\00:\00b\00:\00c\00\00\00") + (data (i32.const 4656) "\06\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\04A\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") (table $0 1 funcref) (elem $0 (i32.const 1)) (export "memory" (memory $0)) @@ -5602,6 +5606,24 @@ local.get $1 call $~lib/string/String#concat ) + (func $templateliteral/RecursiveObject#set:key (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store + local.get $0 + local.get $1 + i32.const 0 + call $~lib/rt/itcms/__link + ) + (func $templateliteral/RecursiveObject#set:val (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + i32.store offset=4 + local.get $0 + local.get $1 + i32.const 0 + call $~lib/rt/itcms/__link + ) (func $start:templateliteral memory.size i32.const 16 @@ -5625,6 +5647,7 @@ call $templateliteral/test_float call $templateliteral/test_fast_paths_string call $templateliteral/test_ref + call $templateliteral/test_recursive ) (func $~lib/rt/__visit_globals (param $0 i32) (local $1 i32) @@ -5697,33 +5720,58 @@ local.get $1 call $~lib/staticarray/StaticArray<~lib/string/String>#__visit ) + (func $templateliteral/RecursiveObject~visit (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load + local.tee $2 + if + local.get $2 + local.get $1 + call $~lib/rt/itcms/__visit + end + local.get $0 + i32.load offset=4 + local.tee $2 + if + local.get $2 + local.get $1 + call $~lib/rt/itcms/__visit + end + ) (func $~lib/rt/__visit_members (param $0 i32) (param $1 i32) block $invalid - block $templateliteral/Ref - block $~lib/staticarray/StaticArray<~lib/string/String> - block $~lib/arraybuffer/ArrayBufferView - block $~lib/string/String - block $~lib/arraybuffer/ArrayBuffer - local.get $0 - i32.const 8 - i32.sub - i32.load - br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $~lib/staticarray/StaticArray<~lib/string/String> $templateliteral/Ref $invalid + block $templateliteral/RecursiveObject + block $templateliteral/Ref + block $~lib/staticarray/StaticArray<~lib/string/String> + block $~lib/arraybuffer/ArrayBufferView + block $~lib/string/String + block $~lib/arraybuffer/ArrayBuffer + local.get $0 + i32.const 8 + i32.sub + i32.load + br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $~lib/staticarray/StaticArray<~lib/string/String> $templateliteral/Ref $templateliteral/RecursiveObject $invalid + end + return end return end + local.get $0 + local.get $1 + call $~lib/arraybuffer/ArrayBufferView~visit return end local.get $0 local.get $1 - call $~lib/arraybuffer/ArrayBufferView~visit + call $~lib/staticarray/StaticArray<~lib/string/String>~visit return end - local.get $0 - local.get $1 - call $~lib/staticarray/StaticArray<~lib/string/String>~visit return end + local.get $0 + local.get $1 + call $templateliteral/RecursiveObject~visit return end unreachable @@ -5742,8 +5790,8 @@ global.get $~lib/memory/__data_end i32.lt_s if - i32.const 20960 - i32.const 21008 + i32.const 21120 + i32.const 21168 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -5754,6 +5802,8 @@ (local $0 i32) (local $1 i32) (local $2 i32) + (local $3 i32) + (local $4 i32) global.get $~lib/memory/__stack_pointer i32.const 24 i32.sub @@ -5778,11 +5828,11 @@ i32.store offset=4 local.get $0 i32.const 32 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=8 - local.get $2 + local.get $4 call $~lib/string/String.__eq i32.eqz if @@ -5796,17 +5846,17 @@ local.get $0 local.get $1 call $~lib/string/String#concat - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=12 - local.get $2 + local.get $4 i32.const 592 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=8 - local.get $2 + local.get $4 call $~lib/string/String.__eq i32.eqz if @@ -5817,48 +5867,52 @@ call $~lib/builtins/abort unreachable end - i32.const 720 + local.get $0 local.set $2 + local.get $1 + local.set $3 + i32.const 720 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=16 - local.get $2 + local.get $4 i32.const 1 - local.get $0 + local.get $2 call $~lib/staticarray/StaticArray<~lib/string/String>#__uset i32.const 720 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=16 - local.get $2 + local.get $4 i32.const 3 - local.get $1 + local.get $3 call $~lib/staticarray/StaticArray<~lib/string/String>#__uset i32.const 720 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=16 - local.get $2 + local.get $4 i32.const 160 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=20 - local.get $2 + local.get $4 call $~lib/staticarray/StaticArray<~lib/string/String>#join - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=12 - local.get $2 + local.get $4 i32.const 768 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=8 - local.get $2 + local.get $4 call $~lib/string/String.__eq i32.eqz if @@ -5878,8 +5932,10 @@ (local $0 i32) (local $1 i32) (local $2 i32) + (local $3 i32) + (local $4 i32) global.get $~lib/memory/__stack_pointer - i32.const 20 + i32.const 24 i32.sub global.set $~lib/memory/__stack_pointer call $~stack_check @@ -5890,8 +5946,8 @@ i64.const 0 i64.store offset=8 global.get $~lib/memory/__stack_pointer - i32.const 0 - i32.store offset=16 + i64.const 0 + i64.store offset=16 i32.const 1 local.set $0 i32.const 2 @@ -5899,17 +5955,17 @@ local.get $0 i32.const 10 call $~lib/number/I32#toString - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store - local.get $2 + local.get $4 i32.const 2592 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=4 - local.get $2 + local.get $4 call $~lib/string/String.__eq i32.eqz if @@ -5923,31 +5979,31 @@ local.get $0 i32.const 10 call $~lib/number/I32#toString - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=8 - local.get $2 + local.get $4 local.get $1 i32.const 10 call $~lib/number/I32#toString - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=12 - local.get $2 + local.get $4 call $~lib/string/String#concat - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store - local.get $2 + local.get $4 i32.const 2624 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=4 - local.get $2 + local.get $4 call $~lib/string/String.__eq i32.eqz if @@ -5958,62 +6014,60 @@ call $~lib/builtins/abort unreachable end - i32.const 2656 - local.set $2 global.get $~lib/memory/__stack_pointer - local.get $2 - i32.store offset=8 - local.get $2 - i32.const 1 local.get $0 i32.const 10 call $~lib/number/I32#toString - local.set $2 - global.get $~lib/memory/__stack_pointer - local.get $2 + local.tee $2 i32.store offset=16 - local.get $2 - call $~lib/staticarray/StaticArray<~lib/string/String>#__uset - i32.const 2656 - local.set $2 global.get $~lib/memory/__stack_pointer - local.get $2 - i32.store offset=8 - local.get $2 - i32.const 3 local.get $1 i32.const 10 call $~lib/number/I32#toString - local.set $2 + local.tee $3 + i32.store offset=20 + i32.const 2656 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 - i32.store offset=16 + local.get $4 + i32.store offset=8 + local.get $4 + i32.const 1 local.get $2 call $~lib/staticarray/StaticArray<~lib/string/String>#__uset i32.const 2656 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=8 - local.get $2 + local.get $4 + i32.const 3 + local.get $3 + call $~lib/staticarray/StaticArray<~lib/string/String>#__uset + i32.const 2656 + local.set $4 + global.get $~lib/memory/__stack_pointer + local.get $4 + i32.store offset=8 + local.get $4 i32.const 160 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=12 - local.get $2 + local.get $4 call $~lib/staticarray/StaticArray<~lib/string/String>#join - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store - local.get $2 + local.get $4 i32.const 2704 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=4 - local.get $2 + local.get $4 call $~lib/string/String.__eq i32.eqz if @@ -6025,7 +6079,7 @@ unreachable end global.get $~lib/memory/__stack_pointer - i32.const 20 + i32.const 24 i32.add global.set $~lib/memory/__stack_pointer ) @@ -6033,8 +6087,10 @@ (local $0 f64) (local $1 f64) (local $2 i32) + (local $3 i32) + (local $4 i32) global.get $~lib/memory/__stack_pointer - i32.const 20 + i32.const 24 i32.sub global.set $~lib/memory/__stack_pointer call $~stack_check @@ -6045,8 +6101,8 @@ i64.const 0 i64.store offset=8 global.get $~lib/memory/__stack_pointer - i32.const 0 - i32.store offset=16 + i64.const 0 + i64.store offset=16 f64.const 1 local.set $0 f64.const 2 @@ -6054,17 +6110,17 @@ local.get $0 i32.const 0 call $~lib/number/F64#toString - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store - local.get $2 + local.get $4 i32.const 3888 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=4 - local.get $2 + local.get $4 call $~lib/string/String.__eq i32.eqz if @@ -6078,31 +6134,31 @@ local.get $0 i32.const 0 call $~lib/number/F64#toString - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=8 - local.get $2 + local.get $4 local.get $1 i32.const 0 call $~lib/number/F64#toString - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=12 - local.get $2 + local.get $4 call $~lib/string/String#concat - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store - local.get $2 + local.get $4 i32.const 3920 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=4 - local.get $2 + local.get $4 call $~lib/string/String.__eq i32.eqz if @@ -6113,62 +6169,60 @@ call $~lib/builtins/abort unreachable end - i32.const 3952 - local.set $2 global.get $~lib/memory/__stack_pointer - local.get $2 - i32.store offset=8 - local.get $2 - i32.const 1 local.get $0 i32.const 0 call $~lib/number/F64#toString - local.set $2 - global.get $~lib/memory/__stack_pointer - local.get $2 + local.tee $2 i32.store offset=16 - local.get $2 - call $~lib/staticarray/StaticArray<~lib/string/String>#__uset - i32.const 3952 - local.set $2 global.get $~lib/memory/__stack_pointer - local.get $2 - i32.store offset=8 - local.get $2 - i32.const 3 local.get $1 i32.const 0 call $~lib/number/F64#toString - local.set $2 + local.tee $3 + i32.store offset=20 + i32.const 3952 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 - i32.store offset=16 + local.get $4 + i32.store offset=8 + local.get $4 + i32.const 1 local.get $2 call $~lib/staticarray/StaticArray<~lib/string/String>#__uset i32.const 3952 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=8 - local.get $2 + local.get $4 + i32.const 3 + local.get $3 + call $~lib/staticarray/StaticArray<~lib/string/String>#__uset + i32.const 3952 + local.set $4 + global.get $~lib/memory/__stack_pointer + local.get $4 + i32.store offset=8 + local.get $4 i32.const 160 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=12 - local.get $2 + local.get $4 call $~lib/staticarray/StaticArray<~lib/string/String>#join - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store - local.get $2 + local.get $4 i32.const 4000 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=4 - local.get $2 + local.get $4 call $~lib/string/String.__eq i32.eqz if @@ -6180,7 +6234,7 @@ unreachable end global.get $~lib/memory/__stack_pointer - i32.const 20 + i32.const 24 i32.add global.set $~lib/memory/__stack_pointer ) @@ -6452,8 +6506,10 @@ (local $0 i32) (local $1 i32) (local $2 i32) + (local $3 i32) + (local $4 i32) global.get $~lib/memory/__stack_pointer - i32.const 28 + i32.const 32 i32.sub global.set $~lib/memory/__stack_pointer call $~stack_check @@ -6467,8 +6523,8 @@ i64.const 0 i64.store offset=16 global.get $~lib/memory/__stack_pointer - i32.const 0 - i32.store offset=24 + i64.const 0 + i64.store offset=24 global.get $~lib/memory/__stack_pointer i32.const 0 i32.const 1 @@ -6483,17 +6539,17 @@ i32.store offset=4 local.get $0 call $templateliteral/Ref#toString - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=8 - local.get $2 + local.get $4 i32.const 4336 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=12 - local.get $2 + local.get $4 call $~lib/string/String.__eq i32.eqz if @@ -6506,30 +6562,30 @@ end local.get $0 call $templateliteral/Ref#toString - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=16 - local.get $2 + local.get $4 local.get $1 call $templateliteral/Ref#toString - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=20 - local.get $2 + local.get $4 call $~lib/string/String#concat - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=8 - local.get $2 + local.get $4 i32.const 4368 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=12 - local.get $2 + local.get $4 call $~lib/string/String.__eq i32.eqz if @@ -6540,72 +6596,238 @@ call $~lib/builtins/abort unreachable end - i32.const 4416 - local.set $2 global.get $~lib/memory/__stack_pointer - local.get $2 - i32.store offset=16 - local.get $2 - i32.const 1 local.get $0 call $templateliteral/Ref#toString - local.set $2 - global.get $~lib/memory/__stack_pointer - local.get $2 + local.tee $2 i32.store offset=24 + global.get $~lib/memory/__stack_pointer + local.get $1 + call $templateliteral/Ref#toString + local.tee $3 + i32.store offset=28 + i32.const 4416 + local.set $4 + global.get $~lib/memory/__stack_pointer + local.get $4 + i32.store offset=16 + local.get $4 + i32.const 1 local.get $2 call $~lib/staticarray/StaticArray<~lib/string/String>#__uset i32.const 4416 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=16 - local.get $2 + local.get $4 i32.const 3 - local.get $1 - call $templateliteral/Ref#toString - local.set $2 - global.get $~lib/memory/__stack_pointer - local.get $2 - i32.store offset=24 - local.get $2 + local.get $3 call $~lib/staticarray/StaticArray<~lib/string/String>#__uset i32.const 4416 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=16 - local.get $2 + local.get $4 i32.const 160 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=20 - local.get $2 + local.get $4 call $~lib/staticarray/StaticArray<~lib/string/String>#join - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer - local.get $2 + local.get $4 i32.store offset=8 - local.get $2 + local.get $4 i32.const 4464 - local.set $2 + local.set $4 global.get $~lib/memory/__stack_pointer + local.get $4 + i32.store offset=12 + local.get $4 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 53 + i32.const 3 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + i32.const 32 + i32.add + global.set $~lib/memory/__stack_pointer + ) + (func $templateliteral/RecursiveObject#toString (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + global.get $~lib/memory/__stack_pointer + i32.const 20 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i64.const 0 + i64.store + global.get $~lib/memory/__stack_pointer + i64.const 0 + i64.store offset=8 + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store offset=16 + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.load offset=4 + local.tee $1 + i32.store + local.get $1 + i32.eqz + if + local.get $0 + i32.load + local.set $4 + global.get $~lib/memory/__stack_pointer + i32.const 20 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $4 + return + end + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.load + local.tee $2 + i32.store offset=4 + global.get $~lib/memory/__stack_pointer + local.get $1 + call $templateliteral/RecursiveObject#toString + local.tee $3 + i32.store offset=8 + i32.const 4592 + local.set $4 + global.get $~lib/memory/__stack_pointer + local.get $4 + i32.store offset=12 + local.get $4 + i32.const 1 local.get $2 + call $~lib/staticarray/StaticArray<~lib/string/String>#__uset + i32.const 4592 + local.set $4 + global.get $~lib/memory/__stack_pointer + local.get $4 + i32.store offset=12 + local.get $4 + i32.const 3 + local.get $3 + call $~lib/staticarray/StaticArray<~lib/string/String>#__uset + i32.const 4592 + local.set $4 + global.get $~lib/memory/__stack_pointer + local.get $4 + i32.store offset=12 + local.get $4 + i32.const 160 + local.set $4 + global.get $~lib/memory/__stack_pointer + local.get $4 + i32.store offset=16 + local.get $4 + call $~lib/staticarray/StaticArray<~lib/string/String>#join + local.set $4 + global.get $~lib/memory/__stack_pointer + i32.const 20 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $4 + ) + (func $templateliteral/test_recursive + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + global.get $~lib/memory/__stack_pointer + i32.const 20 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i64.const 0 + i64.store + global.get $~lib/memory/__stack_pointer + i64.const 0 + i64.store offset=8 + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store offset=16 + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.const 4528 + local.set $3 + global.get $~lib/memory/__stack_pointer + local.get $3 + i32.store + local.get $3 + i32.const 0 + call $templateliteral/RecursiveObject#constructor + local.tee $0 + i32.store offset=4 + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.const 64 + local.set $3 + global.get $~lib/memory/__stack_pointer + local.get $3 + i32.store + local.get $3 + local.get $0 + call $templateliteral/RecursiveObject#constructor + local.tee $1 + i32.store offset=8 + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.const 32 + local.set $3 + global.get $~lib/memory/__stack_pointer + local.get $3 + i32.store + local.get $3 + local.get $1 + call $templateliteral/RecursiveObject#constructor + local.tee $2 i32.store offset=12 local.get $2 + call $templateliteral/RecursiveObject#toString + local.set $3 + global.get $~lib/memory/__stack_pointer + local.get $3 + i32.store offset=16 + local.get $3 + i32.const 4640 + local.set $3 + global.get $~lib/memory/__stack_pointer + local.get $3 + i32.store + local.get $3 call $~lib/string/String.__eq i32.eqz if i32.const 0 i32.const 96 - i32.const 53 + i32.const 118 i32.const 3 call $~lib/builtins/abort unreachable end global.get $~lib/memory/__stack_pointer - i32.const 28 + i32.const 20 i32.add global.set $~lib/memory/__stack_pointer ) @@ -7167,4 +7389,38 @@ global.set $~lib/memory/__stack_pointer local.get $2 ) + (func $templateliteral/RecursiveObject#constructor (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 8 + i32.const 5 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + local.get $1 + call $templateliteral/RecursiveObject#set:key + local.get $0 + local.get $2 + call $templateliteral/RecursiveObject#set:val + local.get $0 + local.set $3 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $3 + ) )