diff --git a/js/src/frontend-rs/frontend-rs.h b/js/src/frontend-rs/frontend-rs.h index 58f33c166841..f48f58f73581 100644 --- a/js/src/frontend-rs/frontend-rs.h +++ b/js/src/frontend-rs/frontend-rs.h @@ -3,8 +3,18 @@ #include #include +struct Bytecode { + uint8_t *data; + uintptr_t len; + uintptr_t capacity; +}; + extern "C" { void asdf(); +void free_bytecode(Bytecode bytecode); + +Bytecode run_jsparagus(const uint8_t *text, uintptr_t text_len); + } // extern "C" diff --git a/js/src/frontend-rs/src/lib.rs b/js/src/frontend-rs/src/lib.rs index a66db10f7cf6..d572e21a5409 100644 --- a/js/src/frontend-rs/src/lib.rs +++ b/js/src/frontend-rs/src/lib.rs @@ -1,10 +1,46 @@ extern crate parser; +use std::mem; +use std::slice; +use std::str; + +#[repr(C)] +pub struct Bytecode { + data: *mut u8, + len: usize, + capacity: usize, +} + +#[no_mangle] +pub unsafe extern "C" fn run_jsparagus(text: *const u8, text_len: usize) -> Bytecode { + let text = str::from_utf8(slice::from_raw_parts(text, text_len)).expect("Invalid UTF8"); + let mut bytecode = jsparagus(text); + let result = Bytecode { + data: bytecode.as_mut_ptr(), + len: bytecode.len(), + capacity: bytecode.capacity(), + }; + mem::forget(bytecode); + result +} + +#[no_mangle] +pub unsafe extern "C" fn free_bytecode(bytecode: Bytecode) { + Vec::from_raw_parts(bytecode.data, bytecode.len, bytecode.capacity); +} + +fn jsparagus(text: &str) -> Vec { + vec![64, 153] // ret + + //vec![64, 112] // null, throw +} + #[no_mangle] pub extern "C" fn asdf() { println!("Hiiiii!"); println!("{:?}", parser::parse_script("2+2")); } + #[cfg(test)] mod tests { #[test] diff --git a/js/src/frontend/Frontend2.cpp b/js/src/frontend/Frontend2.cpp index 84799ea62557..d1ee4b42f654 100644 --- a/js/src/frontend/Frontend2.cpp +++ b/js/src/frontend/Frontend2.cpp @@ -6,6 +6,7 @@ #include "frontend/Frontend2.h" +// #include "frontend-rs/frontend-rs.h" #include "gc/AllocKind.h" using JS::RootedScript; @@ -15,8 +16,14 @@ using namespace js::gc; using namespace js::frontend; using namespace js; +// https://stackoverflow.com/questions/3407012/c-rounding-up-to-the-nearest-multiple-of-a-number +int roundUp(int numToRound, int multiple) { + // assert(multiple && ((multiple & (multiple - 1)) == 0)); + return (numToRound + multiple - 1) & -multiple; +} + bool InitScript(JSContext* cx, HandleScript script, - HandleFunction canoicalFunction) { + HandleFunction canoicalFunction, const Bytecode& bytecode) { uint32_t natoms = 0; if (!script->createScriptData(cx, natoms)) { return false; @@ -37,8 +44,8 @@ bool InitScript(JSContext* cx, HandleScript script, mozilla::Span gcthings = script->data_->gcthings(); gcthings[0] = JS::GCCellPtr(functionProtoScope); - uint32_t codeLength = 1; - uint32_t noteLength = 2; + uint32_t codeLength = bytecode.len; + uint32_t noteLength = roundUp(1 + bytecode.len, 4) - (1 + bytecode.len); uint32_t numResumeOffsets = 0; uint32_t numScopeNotes = 0; uint32_t numTryNotes = 0; @@ -49,32 +56,65 @@ bool InitScript(JSContext* cx, HandleScript script, } jsbytecode* code = script->immutableScriptData()->code(); - code[0] = JSOP_RETRVAL; + for (size_t i = 0; i < codeLength; i++) { + code[i] = bytecode.data[i]; + } jssrcnote* notes = script->immutableScriptData()->notes(); - notes[0] = SRC_NULL; - notes[1] = SRC_NULL; + for (size_t i = 0; i < noteLength; i++) { + notes[i] = SRC_NULL; + } return script->shareScriptData(cx); } -bool Create(JSContext* cx, const char* bytes, size_t length) { +static bool Execute(JSContext* cx, HandleScript script) { + RootedValue result(cx); + result.setUndefined(); + if (!JS_ExecuteScript(cx, script, &result)) { + return false; + } + + if (!result.isUndefined()) { + // Print. + RootedString str(cx, JS_ValueToSource(cx, result)); + if (!str) { + return false; + } + + UniqueChars utf8chars = JS_EncodeStringToUTF8(cx, str); + if (!utf8chars) { + return false; + } + printf("%s\n", utf8chars.get()); + } + return true; +} + +bool Create(JSContext* cx, const uint8_t* bytes, size_t length) { + // void free_bytecode(Bytecode bytecode); + + // Bytecode run_jsparagus(const uint8_t *text, uintptr_t text_len); + + Bytecode bytecode = run_jsparagus(bytes, length); + JS::CompileOptions options(cx); options.setIntroductionType("js shell interactive") .setIsRunOnce(true) .setFileAndLine("typein", 1); - JS::SourceText srcBuf; - if (!srcBuf.init(cx, bytes, length, JS::SourceOwnership::Borrowed)) { - return false; - } + // JS::SourceText srcBuf; + // if (!srcBuf.init(cx, (const char*)bytes, length, + // JS::SourceOwnership::Borrowed)) { + // return false; + // } ScriptSource* ss = cx->new_(); if (!ss) { return false; } - ScriptSourceHolder ssHolder(ss); + ScriptSourceHolder ssHolder(ss); // TODO if (!ss->initFromOptions(cx, options, mozilla::Nothing())) { return false; @@ -105,14 +145,15 @@ bool Create(JSContext* cx, const char* bytes, size_t length) { RootedScript script(cx, JSScript::Create(cx, options, sso, 0, length, 0, length)); - if (!InitScript(cx, script, nullptr)) { + if (!InitScript(cx, script, canoicalFunction, bytecode)) { return false; } - RootedValue result(cx); - if (!JS_ExecuteScript(cx, script, &result)) { + if (!Execute(cx, script)) { return false; } + free_bytecode(bytecode); + return true; } diff --git a/js/src/frontend/Frontend2.h b/js/src/frontend/Frontend2.h index 41dacb72f593..5bab24d5b11b 100644 --- a/js/src/frontend/Frontend2.h +++ b/js/src/frontend/Frontend2.h @@ -17,6 +17,6 @@ bool InitScript(JSContext* cx, JS::HandleScript script, JS::HandleFunction functionProto); -bool Create(JSContext* cx, const char* bytes, size_t length); +bool Create(JSContext* cx, const uint8_t* bytes, size_t length); #endif /* frontend_Frontend2_h */ diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index d595ffccab77..64e79f4cee32 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -36,7 +36,6 @@ #include "builtin/ModuleObject.h" #include "builtin/SelfHostingDefines.h" -#include "frontend-rs/frontend-rs.h" #include "frontend/BytecodeCompiler.h" #include "frontend/FoldConstants.h" #include "frontend/ModuleSharedContext.h" diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 38ff11b4c3d9..8a8ce7a773d5 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -10051,7 +10051,8 @@ static MOZ_MUST_USE bool ProcessArgs(JSContext* cx, OptionParser* op) { #endif // JS_BUILD_BINAST if (op->getBoolOption("rust-frontend")) { - return Create(cx, "x", 1); + AutoReportException are(cx); + return Create(cx, (const unsigned char*)"x", 1); } if (filePaths.empty() && utf8FilePaths.empty() && codeChunks.empty() && diff --git a/js/src/vm/JSScript.h b/js/src/vm/JSScript.h index 8b30e2d5faee..f93cb9c7c417 100644 --- a/js/src/vm/JSScript.h +++ b/js/src/vm/JSScript.h @@ -25,6 +25,7 @@ #include "jstypes.h" +#include "frontend-rs/frontend-rs.h" #include "frontend/BinASTRuntimeSupport.h" #include "frontend/NameAnalysisTypes.h" #include "gc/Barrier.h" @@ -2226,7 +2227,8 @@ class JSScript : public js::BaseScript { js::MutableHandle> scopes); friend bool InitScript(JSContext* cx, JS::HandleScript script, - JS::HandleFunction functionProto); + JS::HandleFunction canoicalFunction, + const Bytecode& bytecode); private: JSScript(JS::Realm* realm, uint8_t* stubEntry,