Skip to content
This repository has been archived by the owner on Aug 4, 2022. It is now read-only.

Commit

Permalink
WIP hooking up rust to c++
Browse files Browse the repository at this point in the history
  • Loading branch information
khyperia committed Aug 8, 2019
1 parent 67240c6 commit 7e1f063
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 19 deletions.
10 changes: 10 additions & 0 deletions js/src/frontend-rs/frontend-rs.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,18 @@
#include <cstdlib>
#include <new>

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"
36 changes: 36 additions & 0 deletions js/src/frontend-rs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<u8> {
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]
Expand Down
71 changes: 56 additions & 15 deletions js/src/frontend/Frontend2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "frontend/Frontend2.h"

// #include "frontend-rs/frontend-rs.h"
#include "gc/AllocKind.h"

using JS::RootedScript;
Expand All @@ -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;
Expand All @@ -37,8 +44,8 @@ bool InitScript(JSContext* cx, HandleScript script,
mozilla::Span<JS::GCCellPtr> 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;
Expand All @@ -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<Utf8Unit> srcBuf;
if (!srcBuf.init(cx, bytes, length, JS::SourceOwnership::Borrowed)) {
return false;
}
// JS::SourceText<Utf8Unit> srcBuf;
// if (!srcBuf.init(cx, (const char*)bytes, length,
// JS::SourceOwnership::Borrowed)) {
// return false;
// }

ScriptSource* ss = cx->new_<ScriptSource>();
if (!ss) {
return false;
}

ScriptSourceHolder ssHolder(ss);
ScriptSourceHolder ssHolder(ss); // TODO

if (!ss->initFromOptions(cx, options, mozilla::Nothing())) {
return false;
Expand Down Expand Up @@ -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;
}
2 changes: 1 addition & 1 deletion js/src/frontend/Frontend2.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
1 change: 0 additions & 1 deletion js/src/frontend/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
3 changes: 2 additions & 1 deletion js/src/shell/js.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() &&
Expand Down
4 changes: 3 additions & 1 deletion js/src/vm/JSScript.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -2226,7 +2227,8 @@ class JSScript : public js::BaseScript {
js::MutableHandle<JS::GCVector<js::Scope*>> 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,
Expand Down

0 comments on commit 7e1f063

Please sign in to comment.