Skip to content

Commit

Permalink
Merge pull request #64 from swiftwasm/minimize-payload
Browse files Browse the repository at this point in the history
Remove payload2 from value bridging interface
  • Loading branch information
kateinoigakukun authored Sep 24, 2020
2 parents a41f9ba + 10bfff2 commit 87c8f73
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 134 deletions.
56 changes: 22 additions & 34 deletions Runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ export class SwiftRuntime {
const argv = exports.swjs_prepare_host_function_call(argc)
for (let index = 0; index < args.length; index++) {
const argument = args[index]
const base = argv + 24 * index
writeValue(argument, base, base + 4, base + 8, base + 16)
const base = argv + 16 * index
writeValue(argument, base, base + 4, base + 8)
}
let output: any;
const callback_func_ref = this.heap.retain(function (result: any) {
Expand Down Expand Up @@ -203,7 +203,7 @@ export class SwiftRuntime {

const decodeValue = (
kind: JavaScriptValueKind,
payload1: number, payload2: number, payload3: number
payload1: number, payload2: number
) => {
switch (kind) {
case JavaScriptValueKind.Boolean: {
Expand All @@ -213,7 +213,7 @@ export class SwiftRuntime {
}
}
case JavaScriptValueKind.Number: {
return payload3;
return payload2;
}
case JavaScriptValueKind.String: {
return readString(payload1);
Expand All @@ -237,50 +237,40 @@ export class SwiftRuntime {

const writeValue = (
value: any, kind_ptr: pointer,
payload1_ptr: pointer, payload2_ptr: pointer, payload3_ptr: pointer
payload1_ptr: pointer, payload2_ptr: pointer
) => {
if (value === null) {
writeUint32(kind_ptr, JavaScriptValueKind.Null);
writeUint32(payload1_ptr, 0);
writeUint32(payload2_ptr, 0);
return;
}
switch (typeof value) {
case "boolean": {
writeUint32(kind_ptr, JavaScriptValueKind.Boolean);
writeUint32(payload1_ptr, value ? 1 : 0);
writeUint32(payload2_ptr, 0);
break;
}
case "number": {
writeUint32(kind_ptr, JavaScriptValueKind.Number);
writeUint32(payload1_ptr, 0);
writeUint32(payload2_ptr, 0);
writeFloat64(payload3_ptr, value);
writeFloat64(payload2_ptr, value);
break;
}
case "string": {
writeUint32(kind_ptr, JavaScriptValueKind.String);
writeUint32(payload1_ptr, this.heap.retain(value));
writeUint32(payload2_ptr, 0);
break;
}
case "undefined": {
writeUint32(kind_ptr, JavaScriptValueKind.Undefined);
writeUint32(payload1_ptr, 0);
writeUint32(payload2_ptr, 0);
break;
}
case "object": {
writeUint32(kind_ptr, JavaScriptValueKind.Object);
writeUint32(payload1_ptr, this.heap.retain(value));
writeUint32(payload2_ptr, 0);
break;
}
case "function": {
writeUint32(kind_ptr, JavaScriptValueKind.Function);
writeUint32(payload1_ptr, this.heap.retain(value));
writeUint32(payload2_ptr, 0);
break;
}
default:
Expand All @@ -289,17 +279,15 @@ export class SwiftRuntime {
}

// Note:
// `decodeValues` assumes that the size of RawJSValue is 24
// and the alignment of it is 8
// `decodeValues` assumes that the size of RawJSValue is 16.
const decodeValues = (ptr: pointer, length: number) => {
let result = []
for (let index = 0; index < length; index++) {
const base = ptr + 24 * index
const base = ptr + 16 * index
const kind = readUInt32(base)
const payload1 = readUInt32(base + 4)
const payload2 = readUInt32(base + 8)
const payload3 = readFloat64(base + 16)
result.push(decodeValue(kind, payload1, payload2, payload3))
const payload2 = readFloat64(base + 8)
result.push(decodeValue(kind, payload1, payload2))
}
return result
}
Expand All @@ -308,36 +296,36 @@ export class SwiftRuntime {
swjs_set_prop: (
ref: ref, name: ref,
kind: JavaScriptValueKind,
payload1: number, payload2: number, payload3: number
payload1: number, payload2: number
) => {
const obj = this.heap.referenceHeap(ref);
Reflect.set(obj, readString(name), decodeValue(kind, payload1, payload2, payload3))
Reflect.set(obj, readString(name), decodeValue(kind, payload1, payload2))
},
swjs_get_prop: (
ref: ref, name: ref,
kind_ptr: pointer,
payload1_ptr: pointer, payload2_ptr: pointer, payload3_ptr: number
payload1_ptr: pointer, payload2_ptr: pointer
) => {
const obj = this.heap.referenceHeap(ref);
const result = Reflect.get(obj, readString(name));
writeValue(result, kind_ptr, payload1_ptr, payload2_ptr, payload3_ptr);
writeValue(result, kind_ptr, payload1_ptr, payload2_ptr);
},
swjs_set_subscript: (
ref: ref, index: number,
kind: JavaScriptValueKind,
payload1: number, payload2: number, payload3: number
payload1: number, payload2: number
) => {
const obj = this.heap.referenceHeap(ref);
Reflect.set(obj, index, decodeValue(kind, payload1, payload2, payload3))
Reflect.set(obj, index, decodeValue(kind, payload1, payload2))
},
swjs_get_subscript: (
ref: ref, index: number,
kind_ptr: pointer,
payload1_ptr: pointer, payload2_ptr: pointer, payload3_ptr: pointer
payload1_ptr: pointer, payload2_ptr: pointer
) => {
const obj = this.heap.referenceHeap(ref);
const result = Reflect.get(obj, index);
writeValue(result, kind_ptr, payload1_ptr, payload2_ptr, payload3_ptr);
writeValue(result, kind_ptr, payload1_ptr, payload2_ptr);
},
swjs_encode_string: (ref: ref, bytes_ptr_result: pointer) => {
const bytes = textEncoder.encode(this.heap.referenceHeap(ref));
Expand All @@ -358,22 +346,22 @@ export class SwiftRuntime {
swjs_call_function: (
ref: ref, argv: pointer, argc: number,
kind_ptr: pointer,
payload1_ptr: pointer, payload2_ptr: pointer, payload3_ptr: pointer
payload1_ptr: pointer, payload2_ptr: pointer
) => {
const func = this.heap.referenceHeap(ref)
const result = Reflect.apply(func, undefined, decodeValues(argv, argc))
writeValue(result, kind_ptr, payload1_ptr, payload2_ptr, payload3_ptr);
writeValue(result, kind_ptr, payload1_ptr, payload2_ptr);
},
swjs_call_function_with_this: (
obj_ref: ref, func_ref: ref,
argv: pointer, argc: number,
kind_ptr: pointer,
payload1_ptr: pointer, payload2_ptr: pointer, payload3_ptr: pointer
payload1_ptr: pointer, payload2_ptr: pointer
) => {
const obj = this.heap.referenceHeap(obj_ref)
const func = this.heap.referenceHeap(func_ref)
const result = Reflect.apply(func, obj, decodeValues(argv, argc))
writeValue(result, kind_ptr, payload1_ptr, payload2_ptr, payload3_ptr);
writeValue(result, kind_ptr, payload1_ptr, payload2_ptr);
},
swjs_create_function: (
host_func_id: number,
Expand Down
39 changes: 37 additions & 2 deletions Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ public class JSFunction: JSObject {
if let thisId = this?.id {
_call_function_with_this(thisId,
self.id, argv, Int32(argc),
&result.kind, &result.payload1, &result.payload2, &result.payload3)
&result.kind, &result.payload1, &result.payload2)
} else {
_call_function(
self.id, argv, Int32(argc),
&result.kind, &result.payload1, &result.payload2, &result.payload3
&result.kind, &result.payload1, &result.payload2
)
}
return result
Expand Down Expand Up @@ -155,6 +155,41 @@ public class JSClosure: JSFunction {
}
}


// MARK: - `JSClosure` mechanism note
//
// 1. Create thunk function in JavaScript world, that has a reference
// to Swift Closure.
// ┌─────────────────────┬──────────────────────────┐
// │ Swift side │ JavaScript side │
// │ │ │
// │ │ │
// │ │ ┌──[Thunk function]──┐ │
// │ ┌ ─ ─ ─ ─ ─│─ ─│─ ─ ─ ─ ─ ┐ │ │
// │ ↓ │ │ │ │ │
// │ [Swift Closure] │ │ Host Function ID │ │
// │ │ │ │ │
// │ │ └────────────────────┘ │
// └─────────────────────┴──────────────────────────┘
//
// 2. When thunk function is invoked, it calls Swift Closure via
// `_call_host_function` and callback the result through callback func
// ┌─────────────────────┬──────────────────────────┐
// │ Swift side │ JavaScript side │
// │ │ │
// │ │ │
// │ Apply ┌──[Thunk function]──┐ │
// │ ┌ ─ ─ ─ ─ ─│─ ─│─ ─ ─ ─ ─ ┐ │ │
// │ ↓ │ │ │ │ │
// │ [Swift Closure] │ │ Host Function ID │ │
// │ │ │ │ │ │
// │ │ │ └────────────────────┘ │
// │ │ │ ↑ │
// │ │ Apply │ │
// │ └─[Result]─┼───>[Callback func]─┘ │
// │ │ │
// └─────────────────────┴──────────────────────────┘

@_cdecl("swjs_prepare_host_function_call")
func _prepare_host_function_call(_ argc: Int32) -> UnsafeMutableRawPointer {
let argumentSize = MemoryLayout<RawJSValue>.size * Int(argc)
Expand Down
2 changes: 1 addition & 1 deletion Sources/JavaScriptKit/FundamentalObjects/JSString.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ extension JSString {

func withRawJSValue<T>(_ body: (RawJSValue) -> T) -> T {
let rawValue = RawJSValue(
kind: .string, payload1: guts.jsRef, payload2: 0, payload3: 0
kind: .string, payload1: guts.jsRef, payload2: 0
)
return body(rawValue)
}
Expand Down
8 changes: 4 additions & 4 deletions Sources/JavaScriptKit/JSValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,29 +149,29 @@ public func getJSValue(this: JSObject, name: JSString) -> JSValue {
var rawValue = RawJSValue()
_get_prop(this.id, name.asInternalJSRef(),
&rawValue.kind,
&rawValue.payload1, &rawValue.payload2, &rawValue.payload3)
&rawValue.payload1, &rawValue.payload2)
return rawValue.jsValue()
}

public func setJSValue(this: JSObject, name: JSString, value: JSValue) {
value.withRawJSValue { rawValue in
_set_prop(this.id, name.asInternalJSRef(), rawValue.kind, rawValue.payload1, rawValue.payload2, rawValue.payload3)
_set_prop(this.id, name.asInternalJSRef(), rawValue.kind, rawValue.payload1, rawValue.payload2)
}
}

public func getJSValue(this: JSObject, index: Int32) -> JSValue {
var rawValue = RawJSValue()
_get_subscript(this.id, index,
&rawValue.kind,
&rawValue.payload1, &rawValue.payload2, &rawValue.payload3)
&rawValue.payload1, &rawValue.payload2)
return rawValue.jsValue()
}

public func setJSValue(this: JSObject, index: Int32, value: JSValue) {
value.withRawJSValue { rawValue in
_set_subscript(this.id, index,
rawValue.kind,
rawValue.payload1, rawValue.payload2, rawValue.payload3)
rawValue.payload1, rawValue.payload2)
}
}

Expand Down
17 changes: 4 additions & 13 deletions Sources/JavaScriptKit/JSValueConvertible.swift
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ extension RawJSValue: JSValueConvertible {
case .boolean:
return .boolean(payload1 != 0)
case .number:
return .number(payload3)
return .number(payload2)
case .string:
return .string(JSString(jsRef: payload1))
case .object:
Expand All @@ -194,8 +194,6 @@ extension RawJSValue: JSValueConvertible {
return .undefined
case .function:
return .function(JSFunction(id: UInt32(payload1)))
default:
fatalError("unreachable")
}
}
}
Expand All @@ -204,38 +202,31 @@ extension JSValue {
func withRawJSValue<T>(_ body: (RawJSValue) -> T) -> T {
let kind: JavaScriptValueKind
let payload1: JavaScriptPayload1
let payload2: JavaScriptPayload2
var payload3: JavaScriptPayload3 = 0
var payload2: JavaScriptPayload2 = 0
switch self {
case let .boolean(boolValue):
kind = .boolean
payload1 = boolValue ? 1 : 0
payload2 = 0
case let .number(numberValue):
kind = .number
payload1 = 0
payload2 = 0
payload3 = numberValue
payload2 = numberValue
case let .string(string):
return string.withRawJSValue(body)
case let .object(ref):
kind = .object
payload1 = JavaScriptPayload1(ref.id)
payload2 = 0
case .null:
kind = .null
payload1 = 0
payload2 = 0
case .undefined:
kind = .undefined
payload1 = 0
payload2 = 0
case let .function(functionRef):
kind = .function
payload1 = JavaScriptPayload1(functionRef.id)
payload2 = 0
}
let rawValue = RawJSValue(kind: kind, payload1: payload1, payload2: payload2, payload3: payload3)
let rawValue = RawJSValue(kind: kind, payload1: payload1, payload2: payload2)
return body(rawValue)
}
}
Expand Down
18 changes: 6 additions & 12 deletions Sources/JavaScriptKit/XcodeSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,28 @@ import _CJavaScriptKit
_: JavaScriptObjectRef,
_: JavaScriptValueKind,
_: JavaScriptPayload1,
_: JavaScriptPayload2,
_: JavaScriptPayload3
_: JavaScriptPayload2
) { fatalError() }
func _get_prop(
_: JavaScriptObjectRef,
_: JavaScriptObjectRef,
_: UnsafeMutablePointer<JavaScriptValueKind>!,
_: UnsafeMutablePointer<JavaScriptPayload1>!,
_: UnsafeMutablePointer<JavaScriptPayload2>!,
_: UnsafeMutablePointer<JavaScriptPayload3>!
_: UnsafeMutablePointer<JavaScriptPayload2>!
) { fatalError() }
func _set_subscript(
_: JavaScriptObjectRef,
_: Int32,
_: JavaScriptValueKind,
_: JavaScriptPayload1,
_: JavaScriptPayload2,
_: JavaScriptPayload3
_: JavaScriptPayload2
) { fatalError() }
func _get_subscript(
_: JavaScriptObjectRef,
_: Int32,
_: UnsafeMutablePointer<JavaScriptValueKind>!,
_: UnsafeMutablePointer<JavaScriptPayload1>!,
_: UnsafeMutablePointer<JavaScriptPayload2>!,
_: UnsafeMutablePointer<JavaScriptPayload3>!
_: UnsafeMutablePointer<JavaScriptPayload2>!
) { fatalError() }
func _encode_string(
_: JavaScriptObjectRef,
Expand All @@ -55,17 +51,15 @@ import _CJavaScriptKit
_: UnsafePointer<RawJSValue>!, _: Int32,
_: UnsafeMutablePointer<JavaScriptValueKind>!,
_: UnsafeMutablePointer<JavaScriptPayload1>!,
_: UnsafeMutablePointer<JavaScriptPayload2>!,
_: UnsafeMutablePointer<JavaScriptPayload3>!
_: UnsafeMutablePointer<JavaScriptPayload2>!
) { fatalError() }
func _call_function_with_this(
_: JavaScriptObjectRef,
_: JavaScriptObjectRef,
_: UnsafePointer<RawJSValue>!, _: Int32,
_: UnsafeMutablePointer<JavaScriptValueKind>!,
_: UnsafeMutablePointer<JavaScriptPayload1>!,
_: UnsafeMutablePointer<JavaScriptPayload2>!,
_: UnsafeMutablePointer<JavaScriptPayload3>!
_: UnsafeMutablePointer<JavaScriptPayload2>!
) { fatalError() }
func _call_new(
_: JavaScriptObjectRef,
Expand Down
Loading

0 comments on commit 87c8f73

Please sign in to comment.