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
1 change: 1 addition & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ under the licensing terms detailed in LICENSE:
* Fabián Heredia Montiel <[email protected]>
* Jonas Minnberg <[email protected]>
* Kam Chehresa <[email protected]>
* Rui Jin <[email protected]>

Portions of this software are derived from third-party works licensed under
the following terms:
Expand Down
39 changes: 29 additions & 10 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ import {
isConstExpressionNaN,
ensureType,
createType,
getConstValueInteger
getConstValueInteger,
isConstZero
} from "./module";

import {
Expand Down Expand Up @@ -10025,6 +10026,14 @@ export class Compiler extends DiagnosticEmitter {

// === Specialized code generation ==============================================================

/** Check if possible to optimize the active initialization away if it's zero */
canOptimizeZeroInitialization(valueExpr: ExpressionRef): bool {
const runtime = this.options.runtime;
return (runtime == Runtime.Incremental || runtime == Runtime.Stub)
? isConstZero(valueExpr)
: false;
}

/** Makes a constant zero of the specified type. */
makeZero(type: Type): ExpressionRef {
let module = this.module;
Expand Down Expand Up @@ -10372,6 +10381,7 @@ export class Compiler extends DiagnosticEmitter {
let parameterIndex = fieldPrototype.parameterIndex;

// Defer non-parameter fields until parameter fields are initialized
// Since non-parameter may depend on parameter fields
if (parameterIndex < 0) {
if (!nonParameterFields) nonParameterFields = new Array();
nonParameterFields.push(property);
Expand Down Expand Up @@ -10407,16 +10417,25 @@ export class Compiler extends DiagnosticEmitter {
let initializerNode = fieldPrototype.initializerNode;
assert(fieldPrototype.parameterIndex < 0);
let setterInstance = assert(field.setterInstance);
let expr = this.makeCallDirect(setterInstance, [
module.local_get(thisLocalIndex, sizeTypeRef),
initializerNode // use initializer if present, otherwise initialize with zero
? this.compileExpression(initializerNode, fieldType, Constraints.ConvImplicit)
: this.makeZero(fieldType)
], field.identifierNode, true);
if (this.currentType != Type.void) { // in case
expr = module.drop(expr);

if (initializerNode) {
// Explicit initializer
// Check if we need to initialize this field
const valueExpr: ExpressionRef = this.compileExpression(initializerNode, fieldType, Constraints.ConvImplicit);
// Memory will be filled with 0 on itcms.__new
// Memory grow will default to initialized with 0 as wasm spec
// So, optimize the active initialization away if it's zero
if (!this.canOptimizeZeroInitialization(valueExpr)) {
let expr = this.makeCallDirect(setterInstance, [
module.local_get(thisLocalIndex, sizeTypeRef),
valueExpr
], field.identifierNode, true);
if (this.currentType != Type.void) { // in case
expr = module.drop(expr);
}
stmts.push(expr);
}
}
stmts.push(expr);
}
}

Expand Down
59 changes: 7 additions & 52 deletions tests/compiler/assignment-chain.debug.wat
Original file line number Diff line number Diff line change
Expand Up @@ -2250,35 +2250,30 @@
local.get $ptr
return
)
(func $assignment-chain/A#set:y (param $this i32) (param $y i64)
local.get $this
local.get $y
i64.store offset=8
)
(func $assignment-chain/A#set:x (param $this i32) (param $x i64)
local.get $this
local.get $x
i64.store
)
(func $assignment-chain/A#set:y (param $this i32) (param $y i64)
(func $assignment-chain/B#get:_setter_cnt (param $this i32) (result i32)
local.get $this
local.get $y
i64.store offset=8
i32.load
)
(func $assignment-chain/B#set:_setter_cnt (param $this i32) (param $_setter_cnt i32)
local.get $this
local.get $_setter_cnt
i32.store
)
(func $assignment-chain/B#set:_getter_cnt (param $this i32) (param $_getter_cnt i32)
local.get $this
local.get $_getter_cnt
i32.store offset=4
)
(func $assignment-chain/B#set:_y (param $this i32) (param $_y f64)
local.get $this
local.get $_y
f64.store offset=8
)
(func $assignment-chain/B#get:_setter_cnt (param $this i32) (result i32)
local.get $this
i32.load
)
(func $assignment-chain/B#get:_getter_cnt (param $this i32) (result i32)
local.get $this
i32.load offset=4
Expand Down Expand Up @@ -2434,22 +2429,6 @@
local.get $this
local.set $1
global.get $~lib/memory/__stack_pointer
local.get $1
i32.store offset=4
local.get $1
i64.const 0
call $assignment-chain/A#set:x
local.get $this
local.set $1
global.get $~lib/memory/__stack_pointer
local.get $1
i32.store offset=4
local.get $1
i64.const 0
call $assignment-chain/A#set:y
local.get $this
local.set $1
global.get $~lib/memory/__stack_pointer
i32.const 8
i32.add
global.set $~lib/memory/__stack_pointer
Expand Down Expand Up @@ -2552,30 +2531,6 @@
local.get $this
local.set $1
global.get $~lib/memory/__stack_pointer
local.get $1
i32.store offset=4
local.get $1
i32.const 0
call $assignment-chain/B#set:_setter_cnt
local.get $this
local.set $1
global.get $~lib/memory/__stack_pointer
local.get $1
i32.store offset=4
local.get $1
i32.const 0
call $assignment-chain/B#set:_getter_cnt
local.get $this
local.set $1
global.get $~lib/memory/__stack_pointer
local.get $1
i32.store offset=4
local.get $1
f64.const 0
call $assignment-chain/B#set:_y
local.get $this
local.set $1
global.get $~lib/memory/__stack_pointer
i32.const 8
i32.add
global.set $~lib/memory/__stack_pointer
Expand Down
34 changes: 2 additions & 32 deletions tests/compiler/assignment-chain.release.wat
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
local.get $0
global.set $~lib/rt/itcms/iter
end
block $__inlined_func$~lib/rt/itcms/Object#unlink$129
block $__inlined_func$~lib/rt/itcms/Object#unlink$124
local.get $1
i32.load offset=4
i32.const -4
Expand All @@ -146,7 +146,7 @@
call $~lib/builtins/abort
unreachable
end
br $__inlined_func$~lib/rt/itcms/Object#unlink$129
br $__inlined_func$~lib/rt/itcms/Object#unlink$124
end
local.get $1
i32.load offset=8
Expand Down Expand Up @@ -1661,18 +1661,6 @@
local.tee $1
i32.store
global.get $~lib/memory/__stack_pointer
local.get $1
i32.store offset=4
local.get $1
i64.const 0
i64.store
global.get $~lib/memory/__stack_pointer
local.get $1
i32.store offset=4
local.get $1
i64.const 0
i64.store offset=8
global.get $~lib/memory/__stack_pointer
i32.const 8
i32.add
global.set $~lib/memory/__stack_pointer
Expand Down Expand Up @@ -1790,24 +1778,6 @@
local.tee $1
i32.store
global.get $~lib/memory/__stack_pointer
local.get $1
i32.store offset=4
local.get $1
i32.const 0
i32.store
global.get $~lib/memory/__stack_pointer
local.get $1
i32.store offset=4
local.get $1
i32.const 0
i32.store offset=4
global.get $~lib/memory/__stack_pointer
local.get $1
i32.store offset=4
local.get $1
f64.const 0
f64.store offset=8
global.get $~lib/memory/__stack_pointer
i32.const 8
i32.add
global.set $~lib/memory/__stack_pointer
Expand Down
Loading
Loading