Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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 {
if ((this.options.runtime != Runtime.Incremental) && (this.options.runtime != Runtime.Stub)) {
return false;
}
return isConstZero(valueExpr);
}

/** 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