diff --git a/Sources/Fuzzilli/Core/CodeGenerators.swift b/Sources/Fuzzilli/Core/CodeGenerators.swift
index d71e5186d..0b45ee637 100644
--- a/Sources/Fuzzilli/Core/CodeGenerators.swift
+++ b/Sources/Fuzzilli/Core/CodeGenerators.swift
@@ -255,6 +255,18 @@ public let CodeGenerators: [CodeGenerator] = [
         b.callMethod(methodName!, on: obj, withArgs: arguments)
     },
 
+    CodeGenerator("MethodCallWithSpreadGenerator", input: .object()) { b, obj in
+        // We cannot currently track element types of Arrays and other Iterable objects and so cannot properly determine argument types when spreading.
+        // For that reason, we don't run this CodeGenerator in conservative mode
+        guard b.mode != .conservative else { return }
+
+        var methodName = b.type(of: obj).randomMethod() ?? b.genMethodName()
+
+        let (arguments, spreads) = b.randCallArgumentsWithSpreading(n: Int.random(in: 3...5))
+
+        b.callMethod(methodName, on: obj, withArgs: arguments, spreading: spreads)
+    },
+
     CodeGenerator("ComputedMethodCallGenerator", input: .object()) { b, obj in
         var methodName = b.type(of: obj).randomMethod()
         if methodName == nil {
@@ -266,6 +278,19 @@ public let CodeGenerators: [CodeGenerator] = [
         b.callComputedMethod(method, on: obj, withArgs: arguments)
     },
 
+    CodeGenerator("ComputedMethodCallWithSpreadGenerator", input: .object()) { b, obj in
+        // We cannot currently track element types of Arrays and other Iterable objects and so cannot properly determine argument types when spreading.
+        // For that reason, we don't run this CodeGenerator in conservative mode
+        guard b.mode != .conservative else { return }
+
+        var methodName = b.type(of: obj).randomMethod() ?? b.genMethodName()
+        let method = b.loadString(methodName)
+
+        let (arguments, spreads) = b.randCallArgumentsWithSpreading(n: Int.random(in: 3...5))
+
+        b.callComputedMethod(method, on: obj, withArgs: arguments, spreading: spreads)
+    },
+
     CodeGenerator("FunctionCallGenerator", input: .function()) { b, f in
         guard let arguments = b.randCallArguments(for: f) else { return }
         b.callFunction(f, withArgs: arguments)
@@ -277,17 +302,25 @@ public let CodeGenerators: [CodeGenerator] = [
     },
 
     CodeGenerator("FunctionCallWithSpreadGenerator", input: .function()) { b, f in
-        // Since we are spreading, the signature doesn't actually help, so ignore it completely
-        guard let arguments = b.randCallArguments(for: FunctionSignature.forUnknownFunction) else { return }
-        
-        // Pick some random arguments to spread.
-        let spreads = arguments.map({ arg in
-            probability(0.75) && b.type(of: arg).Is(.iterable)
-        })
+        // We cannot currently track element types of Arrays and other Iterable objects and so cannot properly determine argument types when spreading.
+        // For that reason, we don't run this CodeGenerator in conservative mode
+        guard b.mode != .conservative else { return }
+
+        let (arguments, spreads) = b.randCallArgumentsWithSpreading(n: Int.random(in: 3...5))
         
         b.callFunction(f, withArgs: arguments, spreading: spreads)
     },
 
+    CodeGenerator("ConstructorCallWithSpreadGenerator", input: .constructor()) { b, c in
+        // We cannot currently track element types of Arrays and other Iterable objects and so cannot properly determine argument types when spreading.
+        // For that reason, we don't run this CodeGenerator in conservative mode
+        guard b.mode != .conservative else { return }
+
+        let (arguments, spreads) = b.randCallArgumentsWithSpreading(n: Int.random(in: 3...5))
+
+        b.construct(c, withArgs: arguments, spreading: spreads)
+    },
+
     CodeGenerator("FunctionReturnGenerator", inContext: .function, input: .anything) { b, val in
         assert(b.context.contains(.function))
         b.doReturn(value: val)
diff --git a/Sources/Fuzzilli/Core/ProgramBuilder.swift b/Sources/Fuzzilli/Core/ProgramBuilder.swift
index cdd1e1dc9..604535e0b 100644
--- a/Sources/Fuzzilli/Core/ProgramBuilder.swift
+++ b/Sources/Fuzzilli/Core/ProgramBuilder.swift
@@ -455,6 +455,23 @@ public class ProgramBuilder {
         return randCallArguments(for: signature)
     }
 
+    public func randCallArgumentsWithSpreading(n: Int) -> (arguments: [Variable], spreads: [Bool]) {
+        var arguments: [Variable] = []
+        var spreads: [Bool] = []
+        for _ in 0...n {
+            let val = randVar()
+            arguments.append(val)
+            // Prefer to spread values that we know are iterable, as non-iterable values will lead to exceptions ("TypeError: Found non-callable @@iterator")
+            if type(of: val).Is(.iterable) {
+                spreads.append(probability(0.9))
+            } else {
+                spreads.append(probability(0.1))
+            }
+        }
+
+        return (arguments, spreads)
+    }
+
     public func generateCallArguments(forMethod methodName: String, on object: Variable) -> [Variable] {
         let signature = methodSignature(of: methodName, on: object)
         return generateCallArguments(for: signature)
@@ -1164,27 +1181,42 @@ public class ProgramBuilder {
 
     @discardableResult
     public func callMethod(_ name: String, on object: Variable, withArgs arguments: [Variable]) -> Variable {
-        return perform(CallMethod(methodName: name, numArguments: arguments.count), withInputs: [object] + arguments).output
+        return perform(CallMethod(methodName: name, numArguments: arguments.count, spreads: [Bool](repeating: false, count: arguments.count)), withInputs: [object] + arguments).output
+    }
+
+    @discardableResult
+    public func callMethod(_ name: String, on object: Variable, withArgs arguments: [Variable], spreading spreads: [Bool]) -> Variable {
+        return perform(CallMethod(methodName: name, numArguments: arguments.count, spreads: spreads), withInputs: [object] + arguments).output
     }
 
     @discardableResult
     public func callComputedMethod(_ name: Variable, on object: Variable, withArgs arguments: [Variable]) -> Variable {
-        return perform(CallComputedMethod(numArguments: arguments.count), withInputs: [object, name] + arguments).output
+        return perform(CallComputedMethod(numArguments: arguments.count, spreads: [Bool](repeating: false, count: arguments.count)), withInputs: [object, name] + arguments).output
+    }
+
+    @discardableResult
+    public func callComputedMethod(_ name: Variable, on object: Variable, withArgs arguments: [Variable], spreading spreads: [Bool]) -> Variable {
+        return perform(CallComputedMethod(numArguments: arguments.count, spreads: spreads), withInputs: [object, name] + arguments).output
     }
 
     @discardableResult
     public func callFunction(_ function: Variable, withArgs arguments: [Variable]) -> Variable {
-        return perform(CallFunction(numArguments: arguments.count), withInputs: [function] + arguments).output
+        return perform(CallFunction(numArguments: arguments.count, spreads: [Bool](repeating: false, count: arguments.count)), withInputs: [function] + arguments).output
     }
 
     @discardableResult
     public func construct(_ constructor: Variable, withArgs arguments: [Variable]) -> Variable {
-        return perform(Construct(numArguments: arguments.count), withInputs: [constructor] + arguments).output
+        return perform(Construct(numArguments: arguments.count, spreads: [Bool](repeating: false, count: arguments.count)), withInputs: [constructor] + arguments).output
     }
 
     @discardableResult
     public func callFunction(_ function: Variable, withArgs arguments: [Variable], spreading spreads: [Bool]) -> Variable {
-        return perform(CallFunctionWithSpread(numArguments: arguments.count, spreads: spreads), withInputs: [function] + arguments).output
+        return perform(CallFunction(numArguments: arguments.count, spreads: spreads), withInputs: [function] + arguments).output
+    }
+
+    @discardableResult
+    public func construct(_ constructor: Variable, withArgs arguments: [Variable], spreading spreads: [Bool]) -> Variable {
+        return perform(Construct(numArguments: arguments.count, spreads: spreads), withInputs: [constructor] + arguments).output
     }
 
     @discardableResult
diff --git a/Sources/Fuzzilli/FuzzIL/AbstractInterpreter.swift b/Sources/Fuzzilli/FuzzIL/AbstractInterpreter.swift
index 2d23de5e6..cc6e2daee 100644
--- a/Sources/Fuzzilli/FuzzIL/AbstractInterpreter.swift
+++ b/Sources/Fuzzilli/FuzzIL/AbstractInterpreter.swift
@@ -395,8 +395,7 @@ public struct AbstractInterpreter {
             let outputType = type(ofInput: 1) | type(ofInput: 2)
             set(instr.output, outputType)
 
-        case is CallFunction,
-             is CallFunctionWithSpread:
+        case is CallFunction:
             set(instr.output, inferCallResultType(of: instr.input(0)))
 
         case let op as CallMethod:
diff --git a/Sources/Fuzzilli/FuzzIL/Instruction.swift b/Sources/Fuzzilli/FuzzIL/Instruction.swift
index b61cb4374..e49d3afc1 100644
--- a/Sources/Fuzzilli/FuzzIL/Instruction.swift
+++ b/Sources/Fuzzilli/FuzzIL/Instruction.swift
@@ -351,15 +351,16 @@ extension Instruction: ProtobufConvertible {
             case is Await:
                 $0.await = Fuzzilli_Protobuf_Await()
             case let op as CallMethod:
-                $0.callMethod = Fuzzilli_Protobuf_CallMethod.with { $0.methodName = op.methodName }
-            case is CallComputedMethod:
-                $0.callComputedMethod = Fuzzilli_Protobuf_CallComputedMethod()
-            case is CallFunction:
-                $0.callFunction = Fuzzilli_Protobuf_CallFunction()
-            case is Construct:
-                $0.construct = Fuzzilli_Protobuf_Construct()
-            case let op as CallFunctionWithSpread:
-                $0.callFunctionWithSpread = Fuzzilli_Protobuf_CallFunctionWithSpread.with { $0.spreads = op.spreads }
+                $0.callMethod = Fuzzilli_Protobuf_CallMethod.with { 
+                    $0.methodName = op.methodName
+                    $0.spreads = op.spreads 
+                }
+            case let op as CallComputedMethod:
+                $0.callComputedMethod = Fuzzilli_Protobuf_CallComputedMethod.with { $0.spreads = op.spreads }
+            case let op as CallFunction:
+                $0.callFunction = Fuzzilli_Protobuf_CallFunction.with { $0.spreads = op.spreads }
+            case let op as Construct:
+                $0.construct = Fuzzilli_Protobuf_Construct.with { $0.spreads = op.spreads }
             case let op as UnaryOperation:
                 $0.unaryOperation = Fuzzilli_Protobuf_UnaryOperation.with { $0.op = convertEnum(op.op, allUnaryOperators) }
             case let op as BinaryOperation:
@@ -584,16 +585,14 @@ extension Instruction: ProtobufConvertible {
         case .await(_):
             op = Await()
         case .callMethod(let p):
-            op = CallMethod(methodName: p.methodName, numArguments: inouts.count - 2)
-        case .callComputedMethod(_):
+            op = CallMethod(methodName: p.methodName, numArguments: inouts.count - 2, spreads: p.spreads)
+        case .callComputedMethod(let p):
             // We subtract 3 from the inouts count since the first two elements are the callee and method and the last element is the output variable
-            op = CallComputedMethod(numArguments: inouts.count - 3)
-        case .callFunction(_):
-            op = CallFunction(numArguments: inouts.count - 2)
-        case .construct(_):
-            op = Construct(numArguments: inouts.count - 2)
-        case .callFunctionWithSpread(let p):
-            op = CallFunctionWithSpread(numArguments: inouts.count - 2, spreads: p.spreads)
+            op = CallComputedMethod(numArguments: inouts.count - 3, spreads: p.spreads)
+        case .callFunction(let p):
+            op = CallFunction(numArguments: inouts.count - 2, spreads: p.spreads)
+        case .construct(let p):
+            op = Construct(numArguments: inouts.count - 2, spreads: p.spreads)
         case .unaryOperation(let p):
             op = UnaryOperation(try convertEnum(p.op, allUnaryOperators))
         case .binaryOperation(let p):
diff --git a/Sources/Fuzzilli/FuzzIL/Operations.swift b/Sources/Fuzzilli/FuzzIL/Operations.swift
index 0f4233591..2f8fde7ec 100644
--- a/Sources/Fuzzilli/FuzzIL/Operations.swift
+++ b/Sources/Fuzzilli/FuzzIL/Operations.swift
@@ -433,54 +433,53 @@ class Await: Operation {
 
 class CallMethod: Operation {
     let methodName: String
+    let spreads: [Bool]
+
     var numArguments: Int {
         return numInputs - 1
     }
     
-    init(methodName: String, numArguments: Int) {
+    init(methodName: String, numArguments: Int, spreads: [Bool]) {
+        assert(spreads.count == numArguments)
         self.methodName = methodName
+        self.spreads = spreads
         // reference object is the first input
         super.init(numInputs: numArguments + 1, numOutputs: 1, attributes: [.isParametric, .isVarargs, .isCall])
     }
 }
 
 class CallComputedMethod: Operation {
+    let spreads: [Bool]
     var numArguments: Int {
         return numInputs - 2
     }
 
-    init(numArguments: Int) {
+    init(numArguments: Int, spreads: [Bool]) {
+        assert(spreads.count == numArguments)
+        self.spreads = spreads
         // reference object is the first input and method name is the second input
         super.init(numInputs: numArguments + 2, numOutputs: 1, attributes: [.isVarargs, .isCall])
     }
 }
 
 class CallFunction: Operation {
-    var numArguments: Int {
-        return numInputs - 1
-    }
+    // Which inputs to spread
+    let spreads: [Bool]
     
-    init(numArguments: Int) {
-        // function object is the first input
-        super.init(numInputs: numArguments + 1, numOutputs: 1, attributes: [.isCall, .isVarargs])
-    }
-}
-
-class Construct: Operation {
     var numArguments: Int {
         return numInputs - 1
     }
     
-    init(numArguments: Int) {
-        // constructor is the first input
-        super.init(numInputs: numArguments + 1, numOutputs: 1, attributes: [.isCall, .isVarargs])
+    init(numArguments: Int, spreads: [Bool]) {
+        assert(spreads.count == numArguments)
+        self.spreads = spreads
+        super.init(numInputs: numArguments + 1, numOutputs: 1, attributes: [.isCall, .isVarargs, .isParametric])
     }
 }
 
-class CallFunctionWithSpread: Operation {
-    // Which inputs to spread
+class Construct: Operation {
     let spreads: [Bool]
-    
+
     var numArguments: Int {
         return numInputs - 1
     }
@@ -488,7 +487,8 @@ class CallFunctionWithSpread: Operation {
     init(numArguments: Int, spreads: [Bool]) {
         assert(spreads.count == numArguments)
         self.spreads = spreads
-        super.init(numInputs: numArguments + 1, numOutputs: 1, attributes: [.isCall, .isVarargs, .isParametric])
+        // constructor is the first input
+        super.init(numInputs: numArguments + 1, numOutputs: 1, attributes: [.isCall, .isVarargs])
     }
 }
 
diff --git a/Sources/Fuzzilli/FuzzIL/Semantics.swift b/Sources/Fuzzilli/FuzzIL/Semantics.swift
index 6a632cf02..d8ffa68e9 100644
--- a/Sources/Fuzzilli/FuzzIL/Semantics.swift
+++ b/Sources/Fuzzilli/FuzzIL/Semantics.swift
@@ -27,7 +27,7 @@ extension Operation {
         case is CallFunction,
              is CallMethod,
              is CallComputedMethod:
-            // We assume that a constructor doesn't modify its arguments when called
+             // We assume that a constructor doesn't modify its arguments when called
             return true
         case is StoreProperty,
              is StoreElement,
diff --git a/Sources/Fuzzilli/Lifting/FuzzILLifter.swift b/Sources/Fuzzilli/Lifting/FuzzILLifter.swift
index 5a9a5098b..8b56854fe 100644
--- a/Sources/Fuzzilli/Lifting/FuzzILLifter.swift
+++ b/Sources/Fuzzilli/Lifting/FuzzILLifter.swift
@@ -152,18 +152,39 @@ public class FuzzILLifter: Lifter {
             w.emit("\(instr.output) <- CallFunction \(input(0)), [\(arguments.joined(separator: ", "))]")
 
         case let op as CallMethod:
-            let arguments = instr.inputs.dropFirst().map({ $0.identifier })
+            var arguments = [String]()
+            for (i, v) in instr.inputs.dropFirst().enumerated() {
+                if op.spreads[i] {
+                    arguments.append("...\(v.identifier)")
+                } else {
+                    arguments.append(v.identifier)
+                }
+            }
             w.emit("\(instr.output) <- CallMethod \(input(0)), '\(op.methodName)', [\(arguments.joined(separator: ", "))]")
 
-        case is CallComputedMethod:
-            let arguments = instr.inputs.dropFirst(2).map({ $0.identifier })
+        case let op as CallComputedMethod:
+            var arguments = [String]()
+            for (i, v) in instr.inputs.dropFirst(2).enumerated() {
+                if op.spreads[i] {
+                    arguments.append("...\(v.identifier)")
+                } else {
+                    arguments.append(v.identifier)
+                }
+            }
             w.emit("\(instr.output) <- CallComputedMethod \(input(0)), \(input(1)), [\(arguments.joined(separator: ", "))]")
 
-        case is Construct:
-            let arguments = instr.inputs.dropFirst().map({ $0.identifier })
-            w.emit("\(instr.output) <- Construct \(input(0)), [\(arguments.joined(separator: ", "))]")
+        case let op as CallFunction:
+            var arguments = [String]()
+            for (i, v) in instr.inputs.dropFirst().enumerated() {
+                if op.spreads[i] {
+                    arguments.append("...\(v.identifier)")
+                } else {
+                    arguments.append(v.identifier)
+                }
+            }
+            w.emit("\(instr.output) <- CallFunction \(input(0)), [\(arguments.joined(separator: ", "))]")
 
-        case let op as CallFunctionWithSpread:
+        case let op as Construct:
             var arguments = [String]()
             for (i, v) in instr.inputs.dropFirst().enumerated() {
                 if op.spreads[i] {
@@ -172,7 +193,7 @@ public class FuzzILLifter: Lifter {
                     arguments.append(v.identifier)
                 }
             }
-            w.emit("\(instr.output) <- CallFunctionWithSpread \(input(0)), [\(arguments.joined(separator: ", "))]")
+            w.emit("\(instr.output) <- Construct \(input(0)), [\(arguments.joined(separator: ", "))]")
 
         case let op as UnaryOperation:
             if op.op.isPostfix {
diff --git a/Sources/Fuzzilli/Lifting/JavaScriptLifter.swift b/Sources/Fuzzilli/Lifting/JavaScriptLifter.swift
index 541d72e88..c63c3ca9e 100644
--- a/Sources/Fuzzilli/Lifting/JavaScriptLifter.swift
+++ b/Sources/Fuzzilli/Lifting/JavaScriptLifter.swift
@@ -336,20 +336,30 @@ public class JavaScriptLifter: Lifter {
                 output = CallExpression.new() <> input(0) <> "(" <> arguments.joined(separator: ",") <> ")"
 
             case let op as CallMethod:
-                let arguments = instr.inputs.dropFirst().map({ expr(for: $0).text })
+                var arguments = [String]()
+                for (i, v) in instr.inputs.dropFirst().enumerated() {
+                    if op.spreads[i] {
+                        arguments.append("..." + expr(for: v).text)
+                    } else {
+                        arguments.append(expr(for: v).text)
+                    }
+                }
                 let method = MemberExpression.new() <> input(0) <> "." <> op.methodName
                 output = CallExpression.new() <> method <> "(" <> arguments.joined(separator: ",") <> ")"
 
-            case is CallComputedMethod:
-                let arguments = instr.inputs.dropFirst(2).map({ expr(for: $0).text })
+            case let op as CallComputedMethod:
+                var arguments = [String]()
+                for (i, v) in instr.inputs.dropFirst(2).enumerated() {
+                    if op.spreads[i] {
+                        arguments.append("..." + expr(for: v).text)
+                    } else {
+                        arguments.append(expr(for: v).text)
+                    }
+                }
                 let method = MemberExpression.new() <> input(0) <> "[" <> input(1) <> "]"
                 output = CallExpression.new() <> method <> "(" <> arguments.joined(separator: ",") <> ")"
 
-            case is Construct:
-                let arguments = instr.inputs.dropFirst().map({ expr(for: $0).text })
-                output = NewExpression.new() <> "new " <> input(0) <> "(" <> arguments.joined(separator: ",") <> ")"
-
-            case let op as CallFunctionWithSpread:
+            case let op as CallFunction:
                 var arguments = [String]()
                 for (i, v) in instr.inputs.dropFirst().enumerated() {
                     if op.spreads[i] {
@@ -360,6 +370,17 @@ public class JavaScriptLifter: Lifter {
                 }
                 output = CallExpression.new() <> input(0) <> "(" <> arguments.joined(separator: ",") <> ")"
 
+            case let op as Construct:
+                var arguments = [String]()
+                for (i, v) in instr.inputs.dropFirst().enumerated() {
+                    if op.spreads[i] {
+                        arguments.append("..." + expr(for: v).text)
+                    } else {
+                        arguments.append(expr(for: v).text)
+                    }
+                }
+                output = NewExpression.new() <> "new " <> input(0) <> "(" <> arguments.joined(separator: ",") <> ")"
+
             case let op as UnaryOperation:
                 if op.op.isPostfix {
                     output = UnaryExpression.new() <> input(0) <> op.op.token
diff --git a/Sources/Fuzzilli/Minimization/CallArgumentReducer.swift b/Sources/Fuzzilli/Minimization/CallArgumentReducer.swift
index 4a3126d3b..6a33ce72f 100644
--- a/Sources/Fuzzilli/Minimization/CallArgumentReducer.swift
+++ b/Sources/Fuzzilli/Minimization/CallArgumentReducer.swift
@@ -29,7 +29,7 @@ struct CallArgumentReducer: Reducer {
                     break
                 }
                 
-                let newOp = CallFunction(numArguments: op.numArguments - 1)
+                let newOp = CallFunction(numArguments: op.numArguments - 1, spreads: op.spreads.dropLast())
                 let newInstr = Instruction(newOp, output: instr.output, inputs: Array(instr.inputs.dropLast()))
                 verifier.tryReplacing(instructionAt: instr.index, with: newInstr, in: &code)
                 
@@ -38,7 +38,7 @@ struct CallArgumentReducer: Reducer {
                     break
                 }
                 
-                let newOp = CallMethod(methodName: op.methodName, numArguments: op.numArguments - 1)
+                let newOp = CallMethod(methodName: op.methodName, numArguments: op.numArguments - 1, spreads: op.spreads.dropLast())
                 let newInstr = Instruction(newOp, output: instr.output, inputs: Array(instr.inputs.dropLast()))
                 verifier.tryReplacing(instructionAt: instr.index, with: newInstr, in: &code)
 
@@ -47,7 +47,7 @@ struct CallArgumentReducer: Reducer {
                     break
                 }
 
-                let newOp = CallComputedMethod(numArguments: op.numArguments - 1)
+                let newOp = CallComputedMethod(numArguments: op.numArguments - 1, spreads: op.spreads.dropLast())
                 let newInstr = Instruction(newOp, output: instr.output, inputs: Array(instr.inputs.dropLast()))
                 verifier.tryReplacing(instructionAt: instr.index, with: newInstr, in: &code)
                 
@@ -56,7 +56,7 @@ struct CallArgumentReducer: Reducer {
                     break
                 }
                 
-                let newOp = Construct(numArguments: op.numArguments - 1)
+                let newOp = Construct(numArguments: op.numArguments - 1, spreads: op.spreads.dropLast())
                 let newInstr = Instruction(newOp, output: instr.output, inputs: Array(instr.inputs.dropLast()))
                 verifier.tryReplacing(instructionAt: instr.index, with: newInstr, in: &code)
                 
diff --git a/Sources/Fuzzilli/Minimization/ReplaceReducer.swift b/Sources/Fuzzilli/Minimization/ReplaceReducer.swift
index 6ad3d69b5..6bb132ab1 100644
--- a/Sources/Fuzzilli/Minimization/ReplaceReducer.swift
+++ b/Sources/Fuzzilli/Minimization/ReplaceReducer.swift
@@ -19,7 +19,7 @@ struct ReplaceReducer: Reducer {
             switch instr.op {
             case let op as Construct:
                 // Try replacing with a simple call
-                let newOp = CallFunction(numArguments: op.numArguments)
+                let newOp = CallFunction(numArguments: op.numArguments, spreads: [Bool](repeating: false, count: op.numArguments))
                 verifier.tryReplacing(instructionAt: instr.index, with: Instruction(newOp, inouts: instr.inouts), in: &code)
             default:
                 break
diff --git a/Sources/Fuzzilli/Mutators/OperationMutator.swift b/Sources/Fuzzilli/Mutators/OperationMutator.swift
index bef10d009..a2d9e8725 100644
--- a/Sources/Fuzzilli/Mutators/OperationMutator.swift
+++ b/Sources/Fuzzilli/Mutators/OperationMutator.swift
@@ -78,14 +78,33 @@ public class OperationMutator: BaseInstructionMutator {
         case is DeleteElement:
             newOp = DeleteElement(index: b.genIndex())
         case let op as CallMethod:
-            newOp = CallMethod(methodName: b.genMethodName(), numArguments: op.numArguments)
-        case let op as CallFunctionWithSpread:
             var spreads = op.spreads
             if spreads.count > 0 {
                 let idx = Int.random(in: 0..<spreads.count)
                 spreads[idx] = !spreads[idx]
             }
-            newOp = CallFunctionWithSpread(numArguments: op.numArguments, spreads: spreads)
+            newOp = CallMethod(methodName: b.genMethodName(), numArguments: op.numArguments, spreads: spreads)
+        case let op as CallComputedMethod:
+            var spreads = op.spreads
+            if spreads.count > 0 {
+                let idx = Int.random(in: 0..<spreads.count)
+                spreads[idx] = !spreads[idx]
+            }
+            newOp = CallComputedMethod(numArguments: op.numArguments, spreads: spreads)
+        case let op as CallFunction:
+            var spreads = op.spreads
+            if spreads.count > 0 {
+                let idx = Int.random(in: 0..<spreads.count)
+                spreads[idx] = !spreads[idx]
+            }
+            newOp = CallFunction(numArguments: op.numArguments, spreads: spreads)
+        case let op as Construct:
+            var spreads = op.spreads
+            if spreads.count > 0 {
+                let idx = Int.random(in: 0..<spreads.count)
+                spreads[idx] = !spreads[idx]
+            }
+            newOp = Construct(numArguments: op.numArguments, spreads: spreads)
         case is UnaryOperation:
             newOp = UnaryOperation(chooseUniform(from: allUnaryOperators))
         case is BinaryOperation:
diff --git a/Sources/Fuzzilli/Protobuf/operations.pb.swift b/Sources/Fuzzilli/Protobuf/operations.pb.swift
index 869948e3e..e13dc091f 100644
--- a/Sources/Fuzzilli/Protobuf/operations.pb.swift
+++ b/Sources/Fuzzilli/Protobuf/operations.pb.swift
@@ -791,6 +791,8 @@ public struct Fuzzilli_Protobuf_CallMethod {
 
   public var methodName: String = String()
 
+  public var spreads: [Bool] = []
+
   public var unknownFields = SwiftProtobuf.UnknownStorage()
 
   public init() {}
@@ -801,6 +803,8 @@ public struct Fuzzilli_Protobuf_CallComputedMethod {
   // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
   // methods supported on all messages.
 
+  public var spreads: [Bool] = []
+
   public var unknownFields = SwiftProtobuf.UnknownStorage()
 
   public init() {}
@@ -811,22 +815,14 @@ public struct Fuzzilli_Protobuf_CallFunction {
   // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
   // methods supported on all messages.
 
-  public var unknownFields = SwiftProtobuf.UnknownStorage()
-
-  public init() {}
-}
-
-public struct Fuzzilli_Protobuf_Construct {
-  // SwiftProtobuf.Message conformance is added in an extension below. See the
-  // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
-  // methods supported on all messages.
+  public var spreads: [Bool] = []
 
   public var unknownFields = SwiftProtobuf.UnknownStorage()
 
   public init() {}
 }
 
-public struct Fuzzilli_Protobuf_CallFunctionWithSpread {
+public struct Fuzzilli_Protobuf_Construct {
   // SwiftProtobuf.Message conformance is added in an extension below. See the
   // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
   // methods supported on all messages.
@@ -2542,6 +2538,7 @@ extension Fuzzilli_Protobuf_CallMethod: SwiftProtobuf.Message, SwiftProtobuf._Me
   public static let protoMessageName: String = _protobuf_package + ".CallMethod"
   public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
     1: .same(proto: "methodName"),
+    2: .same(proto: "spreads"),
   ]
 
   public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@@ -2551,6 +2548,7 @@ extension Fuzzilli_Protobuf_CallMethod: SwiftProtobuf.Message, SwiftProtobuf._Me
       // enabled. https://github.com/apple/swift-protobuf/issues/1034
       switch fieldNumber {
       case 1: try { try decoder.decodeSingularStringField(value: &self.methodName) }()
+      case 2: try { try decoder.decodeRepeatedBoolField(value: &self.spreads) }()
       default: break
       }
     }
@@ -2560,11 +2558,15 @@ extension Fuzzilli_Protobuf_CallMethod: SwiftProtobuf.Message, SwiftProtobuf._Me
     if !self.methodName.isEmpty {
       try visitor.visitSingularStringField(value: self.methodName, fieldNumber: 1)
     }
+    if !self.spreads.isEmpty {
+      try visitor.visitPackedBoolField(value: self.spreads, fieldNumber: 2)
+    }
     try unknownFields.traverse(visitor: &visitor)
   }
 
   public static func ==(lhs: Fuzzilli_Protobuf_CallMethod, rhs: Fuzzilli_Protobuf_CallMethod) -> Bool {
     if lhs.methodName != rhs.methodName {return false}
+    if lhs.spreads != rhs.spreads {return false}
     if lhs.unknownFields != rhs.unknownFields {return false}
     return true
   }
@@ -2572,18 +2574,31 @@ extension Fuzzilli_Protobuf_CallMethod: SwiftProtobuf.Message, SwiftProtobuf._Me
 
 extension Fuzzilli_Protobuf_CallComputedMethod: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
   public static let protoMessageName: String = _protobuf_package + ".CallComputedMethod"
-  public static let _protobuf_nameMap = SwiftProtobuf._NameMap()
+  public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
+    1: .same(proto: "spreads"),
+  ]
 
   public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
-    while let _ = try decoder.nextFieldNumber() {
+    while let fieldNumber = try decoder.nextFieldNumber() {
+      // The use of inline closures is to circumvent an issue where the compiler
+      // allocates stack space for every case branch when no optimizations are
+      // enabled. https://github.com/apple/swift-protobuf/issues/1034
+      switch fieldNumber {
+      case 1: try { try decoder.decodeRepeatedBoolField(value: &self.spreads) }()
+      default: break
+      }
     }
   }
 
   public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
+    if !self.spreads.isEmpty {
+      try visitor.visitPackedBoolField(value: self.spreads, fieldNumber: 1)
+    }
     try unknownFields.traverse(visitor: &visitor)
   }
 
   public static func ==(lhs: Fuzzilli_Protobuf_CallComputedMethod, rhs: Fuzzilli_Protobuf_CallComputedMethod) -> Bool {
+    if lhs.spreads != rhs.spreads {return false}
     if lhs.unknownFields != rhs.unknownFields {return false}
     return true
   }
@@ -2591,18 +2606,31 @@ extension Fuzzilli_Protobuf_CallComputedMethod: SwiftProtobuf.Message, SwiftProt
 
 extension Fuzzilli_Protobuf_CallFunction: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
   public static let protoMessageName: String = _protobuf_package + ".CallFunction"
-  public static let _protobuf_nameMap = SwiftProtobuf._NameMap()
+  public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
+    1: .same(proto: "spreads"),
+  ]
 
   public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
-    while let _ = try decoder.nextFieldNumber() {
+    while let fieldNumber = try decoder.nextFieldNumber() {
+      // The use of inline closures is to circumvent an issue where the compiler
+      // allocates stack space for every case branch when no optimizations are
+      // enabled. https://github.com/apple/swift-protobuf/issues/1034
+      switch fieldNumber {
+      case 1: try { try decoder.decodeRepeatedBoolField(value: &self.spreads) }()
+      default: break
+      }
     }
   }
 
   public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
+    if !self.spreads.isEmpty {
+      try visitor.visitPackedBoolField(value: self.spreads, fieldNumber: 1)
+    }
     try unknownFields.traverse(visitor: &visitor)
   }
 
   public static func ==(lhs: Fuzzilli_Protobuf_CallFunction, rhs: Fuzzilli_Protobuf_CallFunction) -> Bool {
+    if lhs.spreads != rhs.spreads {return false}
     if lhs.unknownFields != rhs.unknownFields {return false}
     return true
   }
@@ -2610,25 +2638,6 @@ extension Fuzzilli_Protobuf_CallFunction: SwiftProtobuf.Message, SwiftProtobuf._
 
 extension Fuzzilli_Protobuf_Construct: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
   public static let protoMessageName: String = _protobuf_package + ".Construct"
-  public static let _protobuf_nameMap = SwiftProtobuf._NameMap()
-
-  public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
-    while let _ = try decoder.nextFieldNumber() {
-    }
-  }
-
-  public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
-    try unknownFields.traverse(visitor: &visitor)
-  }
-
-  public static func ==(lhs: Fuzzilli_Protobuf_Construct, rhs: Fuzzilli_Protobuf_Construct) -> Bool {
-    if lhs.unknownFields != rhs.unknownFields {return false}
-    return true
-  }
-}
-
-extension Fuzzilli_Protobuf_CallFunctionWithSpread: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
-  public static let protoMessageName: String = _protobuf_package + ".CallFunctionWithSpread"
   public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
     1: .same(proto: "spreads"),
   ]
@@ -2652,7 +2661,7 @@ extension Fuzzilli_Protobuf_CallFunctionWithSpread: SwiftProtobuf.Message, Swift
     try unknownFields.traverse(visitor: &visitor)
   }
 
-  public static func ==(lhs: Fuzzilli_Protobuf_CallFunctionWithSpread, rhs: Fuzzilli_Protobuf_CallFunctionWithSpread) -> Bool {
+  public static func ==(lhs: Fuzzilli_Protobuf_Construct, rhs: Fuzzilli_Protobuf_Construct) -> Bool {
     if lhs.spreads != rhs.spreads {return false}
     if lhs.unknownFields != rhs.unknownFields {return false}
     return true
diff --git a/Sources/Fuzzilli/Protobuf/operations.proto b/Sources/Fuzzilli/Protobuf/operations.proto
index d7ba94628..2611d6c75 100644
--- a/Sources/Fuzzilli/Protobuf/operations.proto
+++ b/Sources/Fuzzilli/Protobuf/operations.proto
@@ -175,18 +175,18 @@ message Await {
 
 message CallMethod {
     string methodName = 1;
+    repeated bool spreads = 2;
 }
 
 message CallComputedMethod {
+    repeated bool spreads = 1;
 }
 
 message CallFunction {
+    repeated bool spreads = 1;
 }
 
 message Construct {
-}
-
-message CallFunctionWithSpread {
     repeated bool spreads = 1;
 }
 
diff --git a/Sources/Fuzzilli/Protobuf/program.pb.swift b/Sources/Fuzzilli/Protobuf/program.pb.swift
index 4a068555b..f1417440c 100644
--- a/Sources/Fuzzilli/Protobuf/program.pb.swift
+++ b/Sources/Fuzzilli/Protobuf/program.pb.swift
@@ -510,14 +510,6 @@ public struct Fuzzilli_Protobuf_Instruction {
     set {operation = .construct(newValue)}
   }
 
-  public var callFunctionWithSpread: Fuzzilli_Protobuf_CallFunctionWithSpread {
-    get {
-      if case .callFunctionWithSpread(let v)? = operation {return v}
-      return Fuzzilli_Protobuf_CallFunctionWithSpread()
-    }
-    set {operation = .callFunctionWithSpread(newValue)}
-  }
-
   public var unaryOperation: Fuzzilli_Protobuf_UnaryOperation {
     get {
       if case .unaryOperation(let v)? = operation {return v}
@@ -945,7 +937,6 @@ public struct Fuzzilli_Protobuf_Instruction {
     case callComputedMethod(Fuzzilli_Protobuf_CallComputedMethod)
     case callFunction(Fuzzilli_Protobuf_CallFunction)
     case construct(Fuzzilli_Protobuf_Construct)
-    case callFunctionWithSpread(Fuzzilli_Protobuf_CallFunctionWithSpread)
     case unaryOperation(Fuzzilli_Protobuf_UnaryOperation)
     case binaryOperation(Fuzzilli_Protobuf_BinaryOperation)
     case binaryOperationAndReassign(Fuzzilli_Protobuf_BinaryOperationAndReassign)
@@ -1188,10 +1179,6 @@ public struct Fuzzilli_Protobuf_Instruction {
         guard case .construct(let l) = lhs, case .construct(let r) = rhs else { preconditionFailure() }
         return l == r
       }()
-      case (.callFunctionWithSpread, .callFunctionWithSpread): return {
-        guard case .callFunctionWithSpread(let l) = lhs, case .callFunctionWithSpread(let r) = rhs else { preconditionFailure() }
-        return l == r
-      }()
       case (.unaryOperation, .unaryOperation): return {
         guard case .unaryOperation(let l) = lhs, case .unaryOperation(let r) = rhs else { preconditionFailure() }
         return l == r
@@ -1538,17 +1525,16 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M
     74: .same(proto: "yieldEach"),
     75: .same(proto: "await"),
     31: .same(proto: "callMethod"),
-    96: .same(proto: "callComputedMethod"),
+    34: .same(proto: "callComputedMethod"),
     32: .same(proto: "callFunction"),
     33: .same(proto: "construct"),
-    34: .same(proto: "callFunctionWithSpread"),
     35: .same(proto: "unaryOperation"),
     36: .same(proto: "binaryOperation"),
-    97: .same(proto: "binaryOperationAndReassign"),
+    95: .same(proto: "binaryOperationAndReassign"),
     37: .same(proto: "dup"),
     38: .same(proto: "reassign"),
     39: .same(proto: "compare"),
-    98: .same(proto: "conditionalOperation"),
+    96: .same(proto: "conditionalOperation"),
     40: .same(proto: "eval"),
     87: .same(proto: "beginClassDefinition"),
     88: .same(proto: "beginMethodDefinition"),
@@ -1564,9 +1550,9 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M
     45: .same(proto: "beginIf"),
     46: .same(proto: "beginElse"),
     47: .same(proto: "endIf"),
-    99: .same(proto: "beginSwitch"),
-    100: .same(proto: "beginSwitchCase"),
-    101: .same(proto: "endSwitch"),
+    97: .same(proto: "beginSwitch"),
+    98: .same(proto: "beginSwitchCase"),
+    99: .same(proto: "endSwitch"),
     48: .same(proto: "beginWhile"),
     49: .same(proto: "endWhile"),
     50: .same(proto: "beginDoWhile"),
@@ -1581,7 +1567,7 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M
     59: .same(proto: "continue"),
     60: .same(proto: "beginTry"),
     61: .same(proto: "beginCatch"),
-    95: .same(proto: "beginFinally"),
+    94: .same(proto: "beginFinally"),
     62: .same(proto: "endTryCatch"),
     63: .same(proto: "throwException"),
     81: .same(proto: "beginCodeString"),
@@ -1984,16 +1970,16 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M
         }
       }()
       case 34: try {
-        var v: Fuzzilli_Protobuf_CallFunctionWithSpread?
+        var v: Fuzzilli_Protobuf_CallComputedMethod?
         var hadOneofValue = false
         if let current = self.operation {
           hadOneofValue = true
-          if case .callFunctionWithSpread(let m) = current {v = m}
+          if case .callComputedMethod(let m) = current {v = m}
         }
         try decoder.decodeSingularMessageField(value: &v)
         if let v = v {
           if hadOneofValue {try decoder.handleConflictingOneOf()}
-          self.operation = .callFunctionWithSpread(v)
+          self.operation = .callComputedMethod(v)
         }
       }()
       case 35: try {
@@ -2724,7 +2710,7 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M
           self.operation = .storeSuperProperty(v)
         }
       }()
-      case 95: try {
+      case 94: try {
         var v: Fuzzilli_Protobuf_BeginFinally?
         var hadOneofValue = false
         if let current = self.operation {
@@ -2737,20 +2723,7 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M
           self.operation = .beginFinally(v)
         }
       }()
-      case 96: try {
-        var v: Fuzzilli_Protobuf_CallComputedMethod?
-        var hadOneofValue = false
-        if let current = self.operation {
-          hadOneofValue = true
-          if case .callComputedMethod(let m) = current {v = m}
-        }
-        try decoder.decodeSingularMessageField(value: &v)
-        if let v = v {
-          if hadOneofValue {try decoder.handleConflictingOneOf()}
-          self.operation = .callComputedMethod(v)
-        }
-      }()
-      case 97: try {
+      case 95: try {
         var v: Fuzzilli_Protobuf_BinaryOperationAndReassign?
         var hadOneofValue = false
         if let current = self.operation {
@@ -2763,7 +2736,7 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M
           self.operation = .binaryOperationAndReassign(v)
         }
       }()
-      case 98: try {
+      case 96: try {
         var v: Fuzzilli_Protobuf_ConditionalOperation?
         var hadOneofValue = false
         if let current = self.operation {
@@ -2776,7 +2749,7 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M
           self.operation = .conditionalOperation(v)
         }
       }()
-      case 99: try {
+      case 97: try {
         var v: Fuzzilli_Protobuf_BeginSwitch?
         var hadOneofValue = false
         if let current = self.operation {
@@ -2789,7 +2762,7 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M
           self.operation = .beginSwitch(v)
         }
       }()
-      case 100: try {
+      case 98: try {
         var v: Fuzzilli_Protobuf_BeginSwitchCase?
         var hadOneofValue = false
         if let current = self.operation {
@@ -2802,7 +2775,7 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M
           self.operation = .beginSwitchCase(v)
         }
       }()
-      case 101: try {
+      case 99: try {
         var v: Fuzzilli_Protobuf_EndSwitch?
         var hadOneofValue = false
         if let current = self.operation {
@@ -2961,8 +2934,8 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M
       guard case .construct(let v)? = self.operation else { preconditionFailure() }
       try visitor.visitSingularMessageField(value: v, fieldNumber: 33)
     }()
-    case .callFunctionWithSpread?: try {
-      guard case .callFunctionWithSpread(let v)? = self.operation else { preconditionFailure() }
+    case .callComputedMethod?: try {
+      guard case .callComputedMethod(let v)? = self.operation else { preconditionFailure() }
       try visitor.visitSingularMessageField(value: v, fieldNumber: 34)
     }()
     case .unaryOperation?: try {
@@ -3191,31 +3164,27 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M
     }()
     case .beginFinally?: try {
       guard case .beginFinally(let v)? = self.operation else { preconditionFailure() }
-      try visitor.visitSingularMessageField(value: v, fieldNumber: 95)
-    }()
-    case .callComputedMethod?: try {
-      guard case .callComputedMethod(let v)? = self.operation else { preconditionFailure() }
-      try visitor.visitSingularMessageField(value: v, fieldNumber: 96)
+      try visitor.visitSingularMessageField(value: v, fieldNumber: 94)
     }()
     case .binaryOperationAndReassign?: try {
       guard case .binaryOperationAndReassign(let v)? = self.operation else { preconditionFailure() }
-      try visitor.visitSingularMessageField(value: v, fieldNumber: 97)
+      try visitor.visitSingularMessageField(value: v, fieldNumber: 95)
     }()
     case .conditionalOperation?: try {
       guard case .conditionalOperation(let v)? = self.operation else { preconditionFailure() }
-      try visitor.visitSingularMessageField(value: v, fieldNumber: 98)
+      try visitor.visitSingularMessageField(value: v, fieldNumber: 96)
     }()
     case .beginSwitch?: try {
       guard case .beginSwitch(let v)? = self.operation else { preconditionFailure() }
-      try visitor.visitSingularMessageField(value: v, fieldNumber: 99)
+      try visitor.visitSingularMessageField(value: v, fieldNumber: 97)
     }()
     case .beginSwitchCase?: try {
       guard case .beginSwitchCase(let v)? = self.operation else { preconditionFailure() }
-      try visitor.visitSingularMessageField(value: v, fieldNumber: 100)
+      try visitor.visitSingularMessageField(value: v, fieldNumber: 98)
     }()
     case .endSwitch?: try {
       guard case .endSwitch(let v)? = self.operation else { preconditionFailure() }
-      try visitor.visitSingularMessageField(value: v, fieldNumber: 101)
+      try visitor.visitSingularMessageField(value: v, fieldNumber: 99)
     }()
     case .createTemplateString?: try {
       guard case .createTemplateString(let v)? = self.operation else { preconditionFailure() }
diff --git a/Sources/Fuzzilli/Protobuf/program.proto b/Sources/Fuzzilli/Protobuf/program.proto
index 661e45664..b4e35d0f1 100644
--- a/Sources/Fuzzilli/Protobuf/program.proto
+++ b/Sources/Fuzzilli/Protobuf/program.proto
@@ -71,17 +71,16 @@ message Instruction {
         YieldEach yieldEach = 74;
         Await await = 75;
         CallMethod callMethod = 31;
-        CallComputedMethod callComputedMethod = 96;
+        CallComputedMethod callComputedMethod = 34;
         CallFunction callFunction = 32;
         Construct construct = 33;
-        CallFunctionWithSpread callFunctionWithSpread = 34;
         UnaryOperation unaryOperation = 35;
         BinaryOperation binaryOperation = 36;
-        BinaryOperationAndReassign binaryOperationAndReassign = 97;
+        BinaryOperationAndReassign binaryOperationAndReassign = 95;
         Dup dup = 37;
         Reassign reassign = 38;
         Compare compare = 39;
-        ConditionalOperation conditionalOperation = 98;
+        ConditionalOperation conditionalOperation = 96;
         Eval eval = 40;
         BeginClassDefinition beginClassDefinition = 87;
         BeginMethodDefinition beginMethodDefinition = 88;
@@ -97,9 +96,9 @@ message Instruction {
         BeginIf beginIf = 45;
         BeginElse beginElse = 46;
         EndIf endIf = 47;
-        BeginSwitch beginSwitch = 99;
-        BeginSwitchCase beginSwitchCase = 100;
-        EndSwitch endSwitch = 101;
+        BeginSwitch beginSwitch = 97;
+        BeginSwitchCase beginSwitchCase = 98;
+        EndSwitch endSwitch = 99;
         BeginWhile beginWhile = 48;
         EndWhile endWhile = 49;
         BeginDoWhile beginDoWhile = 50;
@@ -114,7 +113,7 @@ message Instruction {
         Continue continue = 59;
         BeginTry beginTry = 60;
         BeginCatch beginCatch = 61;
-        BeginFinally beginFinally = 95;
+        BeginFinally beginFinally = 94;
         EndTryCatch endTryCatch = 62;
         ThrowException throwException = 63;
         BeginCodeString beginCodeString = 81;
diff --git a/Sources/FuzzilliCli/CodeGeneratorWeights.swift b/Sources/FuzzilliCli/CodeGeneratorWeights.swift
index baf1bd8c0..738be80ba 100644
--- a/Sources/FuzzilliCli/CodeGeneratorWeights.swift
+++ b/Sources/FuzzilliCli/CodeGeneratorWeights.swift
@@ -17,88 +17,91 @@ import Fuzzilli
 /// Assigned weights for the builtin code generators.
 let codeGeneratorWeights = [
     // Base generators
-    "IntegerGenerator":                     2,
-    "RegExpGenerator":                      1,
-    "BigIntGenerator":                      2,
-    "FloatGenerator":                       1,
-    "StringGenerator":                      1,
-    "BooleanGenerator":                     1,
-    "UndefinedGenerator":                   1,
-    "NullGenerator":                        1,
-    "BuiltinGenerator":                     5,
-    "ObjectGenerator":                      10,
-    "ArrayGenerator":                       10,
-    "ObjectWithSpreadGenerator":            5,
-    "ArrayWithSpreadGenerator":             5,
-    "TemplateStringGenerator":              1,
-    "PlainFunctionGenerator":               15,
-    "ArrowFunctionGenerator":               3,
-    "GeneratorFunctionGenerator":           3,
-    "AsyncFunctionGenerator":               3,
-    "AsyncArrowFunctionGenerator":          1,
-    "AsyncGeneratorFunctionGenerator":      1,
-    "FunctionReturnGenerator":              3,
-    "YieldGenerator":                       2,
-    "AwaitGenerator":                       2,
-    "PropertyRetrievalGenerator":           20,
-    "PropertyAssignmentGenerator":          40,
-    "PropertyRemovalGenerator":             5,
-    "ElementRetrievalGenerator":            20,
-    "ElementAssignmentGenerator":           20,
-    "ElementRemovalGenerator":              5,
-    "TypeTestGenerator":                    5,
-    "InstanceOfGenerator":                  5,
-    "InGenerator":                          3,
-    "ComputedPropertyRetrievalGenerator":   20,
-    "ComputedPropertyAssignmentGenerator":  20,
-    "ComputedPropertyRemovalGenerator":     5,
-    "FunctionCallGenerator":                30,
-    "FunctionCallWithSpreadGenerator":      10,
-    "MethodCallGenerator":                  40,
-    "ComputedMethodCallGenerator":          10,
-    "ConstructorCallGenerator":             25,
-    "UnaryOperationGenerator":              25,
-    "BinaryOperationGenerator":             40,
-    "BinaryOperationAndReassignGenerator":  25,
-    "DupGenerator":                         2,
-    "ReassignmentGenerator":                25,
-    "WithStatementGenerator":               5,
-    "LoadFromScopeGenerator":               4,
-    "StoreToScopeGenerator":                4,
-    "ComparisonGenerator":                  10,
-    "ConditionalOperationGenerator":        5,
-    "ClassGenerator":                       20,
-    "SuperMethodCallGenerator":             20,
-    "SuperPropertyOperationGenerator":      10,
-    "IfElseGenerator":                      25,
-    "SwitchCaseGenerator":                  5,
-    "WhileLoopGenerator":                   20,
-    "DoWhileLoopGenerator":                 20,
-    "ForLoopGenerator":                     20,
-    "ForInLoopGenerator":                   10,
-    "ForOfLoopGenerator":                   10,
-    "BreakGenerator":                       5,
-    "ContinueGenerator":                    5,
-    "TryCatchGenerator":                    5,
-    "ThrowGenerator":                       1,
-    "BlockStatementGenerator":              1,
-    
+    "IntegerGenerator":                      2,
+    "RegExpGenerator":                       1,
+    "BigIntGenerator":                       2,
+    "FloatGenerator":                        1,
+    "StringGenerator":                       1,
+    "BooleanGenerator":                      1,
+    "UndefinedGenerator":                    1,
+    "NullGenerator":                         1,
+    "BuiltinGenerator":                      5,
+    "ObjectGenerator":                       10,
+    "ArrayGenerator":                        10,
+    "ObjectWithSpreadGenerator":             5,
+    "ArrayWithSpreadGenerator":              5,
+    "TemplateStringGenerator":               1,
+    "PlainFunctionGenerator":                15,
+    "ArrowFunctionGenerator":                3,
+    "GeneratorFunctionGenerator":            3,
+    "AsyncFunctionGenerator":                3,
+    "AsyncArrowFunctionGenerator":           1,
+    "AsyncGeneratorFunctionGenerator":       1,
+    "FunctionReturnGenerator":               3,
+    "YieldGenerator":                        2,
+    "AwaitGenerator":                        2,
+    "PropertyRetrievalGenerator":            20,
+    "PropertyAssignmentGenerator":           40,
+    "PropertyRemovalGenerator":              5,
+    "ElementRetrievalGenerator":             20,
+    "ElementAssignmentGenerator":            20,
+    "ElementRemovalGenerator":               5,
+    "TypeTestGenerator":                     5,
+    "InstanceOfGenerator":                   5,
+    "InGenerator":                           3,
+    "ComputedPropertyRetrievalGenerator":    20,
+    "ComputedPropertyAssignmentGenerator":   20,
+    "ComputedPropertyRemovalGenerator":      5,
+    "FunctionCallGenerator":                 30,
+    "FunctionCallWithSpreadGenerator":       10,
+    "MethodCallGenerator":                   40,
+    "MethodCallWithSpreadGenerator":         10,
+    "ComputedMethodCallGenerator":           10,
+    "ComputedMethodCallWithSpreadGenerator": 4,
+    "ConstructorCallGenerator":              25,
+    "ConstructorCallWithSpreadGenerator":    10,
+    "UnaryOperationGenerator":               25,
+    "BinaryOperationGenerator":              40,
+    "BinaryOperationAndReassignGenerator":   25,
+    "DupGenerator":                          2,
+    "ReassignmentGenerator":                 25,
+    "WithStatementGenerator":                5,
+    "LoadFromScopeGenerator":                4,
+    "StoreToScopeGenerator":                 4,
+    "ComparisonGenerator":                   10,
+    "ConditionalOperationGenerator":         5,
+    "ClassGenerator":                        20,
+    "SuperMethodCallGenerator":              20,
+    "SuperPropertyOperationGenerator":       10,
+    "IfElseGenerator":                       25,
+    "SwitchCaseGenerator":                   5,
+    "WhileLoopGenerator":                    20,
+    "DoWhileLoopGenerator":                  20,
+    "ForLoopGenerator":                      20,
+    "ForInLoopGenerator":                    10,
+    "ForOfLoopGenerator":                    10,
+    "BreakGenerator":                        5,
+    "ContinueGenerator":                     5,
+    "TryCatchGenerator":                     5,
+    "ThrowGenerator":                        1,
+    "BlockStatementGenerator":               1,
+
     // Special generators
-    "WellKnownPropertyLoadGenerator":       5,
-    "WellKnownPropertyStoreGenerator":      5,
-    "TypedArrayGenerator":                  10,
-    "FloatArrayGenerator":                  5,
-    "IntArrayGenerator":                    5,
-    "ObjectArrayGenerator":                 5,
-    "PrototypeAccessGenerator":             15,
-    "PrototypeOverwriteGenerator":          15,
-    "CallbackPropertyGenerator":            15,
-    "PropertyAccessorGenerator":            15,
-    "MethodCallWithDifferentThisGenerator": 5,
-    "ProxyGenerator":                       15,
-    "LengthChangeGenerator":                5,
-    "ElementKindChangeGenerator":           5,
-    "PromiseGenerator":                     3,
-    "EvalGenerator":                        3,
-    "MathOperationGenerator":               10,
+    "WellKnownPropertyLoadGenerator":        5,
+    "WellKnownPropertyStoreGenerator":       5,
+    "TypedArrayGenerator":                   10,
+    "FloatArrayGenerator":                   5,
+    "IntArrayGenerator":                     5,
+    "ObjectArrayGenerator":                  5,
+    "PrototypeAccessGenerator":              15,
+    "PrototypeOverwriteGenerator":           15,
+    "CallbackPropertyGenerator":             15,
+    "PropertyAccessorGenerator":             15,
+    "MethodCallWithDifferentThisGenerator":  5,
+    "ProxyGenerator":                        15,
+    "LengthChangeGenerator":                 5,
+    "ElementKindChangeGenerator":            5,
+    "PromiseGenerator":                      3,
+    "EvalGenerator":                         3,
+    "MathOperationGenerator":                10,
 ]
diff --git a/Tests/FuzzilliTests/LifterTest.swift b/Tests/FuzzilliTests/LifterTest.swift
index 5d431aa5e..9ff365f55 100644
--- a/Tests/FuzzilliTests/LifterTest.swift
+++ b/Tests/FuzzilliTests/LifterTest.swift
@@ -733,8 +733,8 @@ class LifterTests: XCTestCase {
         let _ = b.deleteElement(3, of: v10)
 
         let program = b.finalize()
-
         let lifted_program = fuzzer.lifter.lift(program)
+
         let expected_program = """
         const v3 = {"bar":13.37,"foo":1337};
         const v4 = delete v3.foo;
@@ -813,7 +813,6 @@ class LifterTests: XCTestCase {
         let v1 = b.loadRegExp("b", RegExpFlags())
         b.compare(v0,v1, with: .equal);
 
-
         let program = b.finalize()
 
         let lifted_program = fuzzer.lifter.lift(program)
@@ -822,6 +821,98 @@ class LifterTests: XCTestCase {
         const v1 = v0 == v0;
         const v2 = /b/;
         const v3 = v0 == v2;
+
+        """
+
+        XCTAssertEqual(lifted_program,expected_program)
+    }
+
+    
+    func testCallMethodWithSpreadLifting(){
+        let fuzzer = makeMockFuzzer()
+        let b = fuzzer.makeBuilder()
+
+        var initialValues = [Variable]()
+        initialValues.append(b.loadInt(1))
+        initialValues.append(b.loadInt(3))
+        initialValues.append(b.loadInt(9))
+        initialValues.append(b.loadInt(10))
+        initialValues.append(b.loadInt(2))
+        initialValues.append(b.loadInt(6))
+        let v6 = b.createArray(with: initialValues)
+
+        let v7 = b.loadInt(0)
+        let v8 = b.loadInt(4)
+
+        let v9 = b.loadBuiltin("Math")
+        let _ = b.callMethod("max", on: v9, withArgs: [v7,v6,v8], spreading: [false, true, false])
+
+        let program = b.finalize()
+
+        let lifted_program = fuzzer.lifter.lift(program)
+        let expected_program = """
+        const v6 = [1,3,9,10,2,6];
+        const v10 = Math.max(0,...v6,4);
+
+        """
+
+        XCTAssertEqual(lifted_program,expected_program)
+    }
+
+    func testCallComputedMethodWithSpreadLifting(){
+        let fuzzer = makeMockFuzzer()
+        let b = fuzzer.makeBuilder()
+
+        let v0 = b.definePlainFunction(withSignature: FunctionSignature(withParameterCount: 2)) { args in
+            let v3 = b.binary(args[0], args[1], with: .Add)
+            b.doReturn(value: v3)
+        }
+        let v4 = b.createObject(with: ["add" : v0])
+        let v5 = b.loadString("add")
+        var initialValues = [Variable]()
+        initialValues.append(b.loadInt(15))
+        initialValues.append(b.loadInt(30))
+        let v8 = b.createArray(with: initialValues)
+        let _ = b.callComputedMethod(v5, on: v4, withArgs: [v8], spreading: [true])
+
+        let program = b.finalize()
+
+        let lifted_program = fuzzer.lifter.lift(program)
+        let expected_program = """
+        function v0(v1,v2) {
+            const v3 = v1 + v2;
+            return v3;
+        }
+        const v4 = {"add":v0};
+        const v8 = [15,30];
+        const v9 = v4["add"](...v8);
+
+        """
+
+        XCTAssertEqual(lifted_program,expected_program)
+    }
+
+    func testConstructWithSpreadLifting(){
+        let fuzzer = makeMockFuzzer()
+        let b = fuzzer.makeBuilder()
+
+        var initialValues = [Variable]()
+        initialValues.append(b.loadInt(15))
+        initialValues.append(b.loadInt(30))
+        initialValues.append(b.loadString("Hello"))
+        initialValues.append(b.loadString("World"))
+        let v4 = b.createArray(with: initialValues)
+        let v5 = b.loadFloat(13.37)
+
+        let v6 = b.loadBuiltin("Array")
+        let _ = b.construct(v6, withArgs: [v4,v5], spreading: [true,false])
+
+        let program = b.finalize()
+
+        let lifted_program = fuzzer.lifter.lift(program)
+        let expected_program = """
+        const v4 = [15,30,"Hello","World"];
+        const v7 = new Array(...v4,13.37);
         
         """
 
@@ -853,6 +944,9 @@ extension LifterTests {
             ("testDeleteOpsLifting", testDeleteOpsLifting),
             ("testRegExpInline",testRegExpInline),
             ("testStrictFunctionLifting", testStrictFunctionLifting),
+            ("testCallMethodWithSpreadLifting", testCallMethodWithSpreadLifting),
+            ("testCallComputedMethodWithSpreadLifting", testCallComputedMethodWithSpreadLifting),
+            ("testConstructWithSpreadLifting", testConstructWithSpreadLifting),
         ]
     }
 }
