Skip to content

Commit b94fea6

Browse files
committed
fix: Remove unsafety by moving Executable to a heap vector
1 parent 386b318 commit b94fea6

File tree

17 files changed

+3374
-3256
lines changed

17 files changed

+3374
-3256
lines changed

nova_vm/src/ecmascript/builtins/builtin_constructor.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::{
2626
BUILTIN_STRING_MEMORY,
2727
},
2828
},
29-
engine::{Executable, HeapAllocatedBytecode},
29+
engine::Executable,
3030
heap::{
3131
indexes::BuiltinConstructorIndex, CompactionLists, CreateHeapData, Heap, HeapMarkAndSweep,
3232
ObjectEntry, ObjectEntryPropertyDescriptor, WorkQueues,
@@ -411,17 +411,13 @@ pub(crate) fn create_builtin_constructor(
411411
agent.heap.create_null_object(&entries)
412412
};
413413

414-
let compiled_initializer_bytecode = args
415-
.compiled_initializer_bytecode
416-
.map(HeapAllocatedBytecode::new);
417-
418414
// 13. Return func.
419415
agent.heap.create(BuiltinConstructorHeapData {
420416
// 10. Perform SetFunctionLength(func, length).
421417
// Skipped as length of builtin constructors is always 0.
422418
// 8. Set func.[[Realm]] to realm.
423419
realm,
424-
compiled_initializer_bytecode,
420+
compiled_initializer_bytecode: args.compiled_initializer_bytecode,
425421
is_derived: args.is_derived,
426422
object_index: Some(backing_object),
427423
environment: args.env,

nova_vm/src/ecmascript/builtins/control_abstraction_objects/generator_objects.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ use crate::{
1515
InternalMethods, InternalSlots, IntoObject, IntoValue, Object, OrdinaryObject, Value,
1616
},
1717
},
18-
engine::{
19-
local_value::ObjectScopeRoot, ExecutionResult, HeapAllocatedBytecode, SuspendedVm, Vm,
20-
},
18+
engine::{local_value::ObjectScopeRoot, Executable, ExecutionResult, SuspendedVm, Vm},
2119
heap::{
2220
indexes::{BaseIndex, GeneratorIndex},
2321
CompactionLists, CreateHeapData, Heap, HeapMarkAndSweep, WorkQueues,
@@ -365,7 +363,7 @@ pub(crate) enum GeneratorState {
365363
// SUSPENDED-START has `vm_or_args` set to Arguments, SUSPENDED-YIELD has it set to Vm.
366364
Suspended {
367365
vm_or_args: VmOrArguments,
368-
executable: HeapAllocatedBytecode,
366+
executable: Executable,
369367
execution_context: ExecutionContext,
370368
},
371369
Executing,

nova_vm/src/ecmascript/builtins/global_object.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use crate::{
2828
},
2929
types::{Function, IntoValue, String, Value, BUILTIN_STRING_MEMORY},
3030
},
31-
engine::{Executable, HeapAllocatedBytecode, Vm},
31+
engine::{Executable, Vm},
3232
heap::IntrinsicFunctionIndexes,
3333
};
3434

@@ -335,13 +335,13 @@ pub fn perform_eval(
335335
// allocation for no good reason.
336336
// Second, this executable is not accessible by the heap and will thus
337337
// break if garbage collection triggers within the eval.
338-
let exe = HeapAllocatedBytecode::new(Executable::compile_eval_body(agent, &script.body));
338+
let exe = Executable::compile_eval_body(agent, &script.body);
339339
// a. Set result to Completion(Evaluation of body).
340340
// 30. If result is a normal completion and result.[[Value]] is empty, then
341341
// a. Set result to NormalCompletion(undefined).
342342
let result = Vm::execute(agent, exe, None).into_js_result();
343343
// SAFETY: No one can access the bytecode anymore.
344-
unsafe { exe.drop() };
344+
unsafe { exe.try_drop(agent) };
345345
result
346346
} else {
347347
Err(result.err().unwrap())

nova_vm/src/ecmascript/scripts_and_modules/script.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::{
1919
},
2020
types::{IntoValue, String, Value, BUILTIN_STRING_MEMORY},
2121
},
22-
engine::{Executable, HeapAllocatedBytecode, Vm},
22+
engine::{Executable, Vm},
2323
heap::{CompactionLists, HeapMarkAndSweep, WorkQueues},
2424
};
2525
use ahash::AHashSet;
@@ -141,7 +141,7 @@ pub struct Script {
141141
pub(crate) ecmascript_code: ManuallyDrop<Program<'static>>,
142142

143143
/// Stores the compiled bytecode of a Script.
144-
pub(crate) compiled_bytecode: Option<HeapAllocatedBytecode>,
144+
pub(crate) compiled_bytecode: Option<Executable>,
145145

146146
/// ### \[\[LoadedModules]]
147147
///
@@ -306,7 +306,7 @@ pub fn script_evaluation(agent: &mut Agent, script: Script) -> JsResult<Value> {
306306

307307
// 13. If result.[[Type]] is normal, then
308308
let result: JsResult<Value> = if result.is_ok() {
309-
let bytecode = HeapAllocatedBytecode::new(Executable::compile_script(agent, script));
309+
let bytecode = Executable::compile_script(agent, script);
310310
agent[script].compiled_bytecode = Some(bytecode);
311311
// a. Set result to Completion(Evaluation of script).
312312
// b. If result.[[Type]] is normal and result.[[Value]] is empty, then

nova_vm/src/ecmascript/syntax_directed_operations/function_definitions.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use crate::{
3434
Value, BUILTIN_STRING_MEMORY,
3535
},
3636
},
37-
engine::{Executable, ExecutionResult, FunctionExpression, HeapAllocatedBytecode, Vm},
37+
engine::{Executable, ExecutionResult, FunctionExpression, Vm},
3838
heap::CreateHeapData,
3939
};
4040
use oxc_ast::ast::{self};
@@ -271,7 +271,7 @@ pub(crate) fn evaluate_function_body(
271271
exe
272272
} else {
273273
let data = CompileFunctionBodyData::new(agent, function_object);
274-
let exe = HeapAllocatedBytecode::new(Executable::compile_function_body(agent, data));
274+
let exe = Executable::compile_function_body(agent, data);
275275
agent[function_object].compiled_bytecode = Some(exe);
276276
exe
277277
};
@@ -298,7 +298,7 @@ pub(crate) fn evaluate_async_function_body(
298298
exe
299299
} else {
300300
let data = CompileFunctionBodyData::new(agent, function_object);
301-
let exe = HeapAllocatedBytecode::new(Executable::compile_function_body(agent, data));
301+
let exe = Executable::compile_function_body(agent, data);
302302
agent[function_object].compiled_bytecode = Some(exe);
303303
exe
304304
};
@@ -375,7 +375,7 @@ pub(crate) fn evaluate_generator_body(
375375
// 4. Perform GeneratorStart(G, FunctionBody).
376376
// SAFETY: We're alive so SourceCode must be too.
377377
let data = CompileFunctionBodyData::new(agent, function_object);
378-
let executable = HeapAllocatedBytecode::new(Executable::compile_function_body(agent, data));
378+
let executable = Executable::compile_function_body(agent, data);
379379
agent[generator].generator_state = Some(GeneratorState::Suspended {
380380
vm_or_args: VmOrArguments::Arguments(arguments_list.0.into()),
381381
executable,

nova_vm/src/ecmascript/types/language/function/data.rs

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
scripts_and_modules::source_code::SourceCode,
1212
types::{OrdinaryObject, String, Value},
1313
},
14-
engine::HeapAllocatedBytecode,
14+
engine::Executable,
1515
heap::element_array::ElementsVector,
1616
};
1717

@@ -66,7 +66,7 @@ pub struct BuiltinConstructorHeapData {
6666
/// Base.
6767
pub(crate) is_derived: bool,
6868
/// Stores the compiled bytecode of class field initializers.
69-
pub(crate) compiled_initializer_bytecode: Option<HeapAllocatedBytecode>,
69+
pub(crate) compiled_initializer_bytecode: Option<Executable>,
7070
/// ### \[\[Environment]]
7171
///
7272
/// This is required for class field initializers.
@@ -85,38 +85,14 @@ pub struct BuiltinConstructorHeapData {
8585
pub(crate) source_code: SourceCode,
8686
}
8787

88-
// SAFETY: We promise not to ever mutate the Executable, especially not from
89-
// foreign threads.
90-
unsafe impl Send for BuiltinConstructorHeapData {}
91-
92-
impl Drop for BuiltinConstructorHeapData {
93-
fn drop(&mut self) {
94-
if let Some(exe) = self.compiled_initializer_bytecode.take() {
95-
// SAFETY: No references to this compiled bytecode should exist as
96-
// otherwise we should not have been garbage collected.
97-
unsafe { exe.drop() };
98-
}
99-
}
100-
}
101-
10288
#[derive(Debug)]
10389
pub struct ECMAScriptFunctionHeapData {
10490
pub(crate) object_index: Option<OrdinaryObject>,
10591
pub(crate) length: u8,
10692
pub(crate) ecmascript_function: ECMAScriptFunctionObjectHeapData,
10793
/// Stores the compiled bytecode of an ECMAScript function.
108-
pub(crate) compiled_bytecode: Option<HeapAllocatedBytecode>,
94+
pub(crate) compiled_bytecode: Option<Executable>,
10995
pub(crate) name: Option<String>,
11096
}
11197

11298
unsafe impl Send for ECMAScriptFunctionHeapData {}
113-
114-
impl Drop for ECMAScriptFunctionHeapData {
115-
fn drop(&mut self) {
116-
if let Some(exe) = self.compiled_bytecode.take() {
117-
// SAFETY: No references to this compiled bytecode should exist as
118-
// otherwise we should not have been garbage collected.
119-
unsafe { exe.drop() };
120-
}
121-
}
122-
}

nova_vm/src/engine/bytecode.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5+
mod bytecode_compiler;
56
mod executable;
6-
mod heap_allocated_bytecode;
77
mod instructions;
88
pub(super) mod iterator;
99
mod vm;
1010

11+
pub(crate) use bytecode_compiler::{
12+
is_reference, CompileContext, CompileEvaluation, NamedEvaluationParameter,
13+
};
1114
pub(crate) use executable::{
12-
is_reference, CompileContext, CompileEvaluation, Executable, FunctionExpression, IndexType,
13-
NamedEvaluationParameter, SendableRef,
15+
Executable, ExecutableHeapData, FunctionExpression, IndexType, SendableRef,
1416
};
15-
pub(crate) use heap_allocated_bytecode::HeapAllocatedBytecode;
1617
pub(crate) use instructions::{Instruction, InstructionIter};
1718
pub(crate) use vm::{instanceof_operator, ExecutionResult, SuspendedVm, Vm};

0 commit comments

Comments
 (0)