зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1638470 - Update jsparagus, and update SmooshMonkey to store atoms in gcthings. r=yulia
Differential Revision: https://phabricator.services.mozilla.com/D75711
This commit is contained in:
Родитель
9443c95639
Коммит
2ac5bccc9b
|
@ -30,7 +30,7 @@ rev = "77a7f5eb12a8d93f2bd71bd4d844405e06743365"
|
|||
[source."https://github.com/mozilla-spidermonkey/jsparagus"]
|
||||
git = "https://github.com/mozilla-spidermonkey/jsparagus"
|
||||
replace-with = "vendored-sources"
|
||||
rev = "9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
rev = "ce731ef6014c41b1691a9be3480fbc43e5e9a396"
|
||||
|
||||
[source."https://github.com/kvark/spirv_cross"]
|
||||
branch = "wgpu3"
|
||||
|
|
|
@ -2367,7 +2367,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "jsparagus"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=ce731ef6014c41b1691a9be3480fbc43e5e9a396#ce731ef6014c41b1691a9be3480fbc43e5e9a396"
|
||||
dependencies = [
|
||||
"jsparagus-ast",
|
||||
"jsparagus-emitter",
|
||||
|
@ -2380,7 +2380,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "jsparagus-ast"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=ce731ef6014c41b1691a9be3480fbc43e5e9a396#ce731ef6014c41b1691a9be3480fbc43e5e9a396"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"indexmap",
|
||||
|
@ -2391,7 +2391,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "jsparagus-emitter"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=ce731ef6014c41b1691a9be3480fbc43e5e9a396#ce731ef6014c41b1691a9be3480fbc43e5e9a396"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"byteorder",
|
||||
|
@ -2403,7 +2403,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "jsparagus-generated-parser"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=ce731ef6014c41b1691a9be3480fbc43e5e9a396#ce731ef6014c41b1691a9be3480fbc43e5e9a396"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"jsparagus-ast",
|
||||
|
@ -2413,12 +2413,12 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "jsparagus-json-log"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=ce731ef6014c41b1691a9be3480fbc43e5e9a396#ce731ef6014c41b1691a9be3480fbc43e5e9a396"
|
||||
|
||||
[[package]]
|
||||
name = "jsparagus-parser"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=ce731ef6014c41b1691a9be3480fbc43e5e9a396#ce731ef6014c41b1691a9be3480fbc43e5e9a396"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"jsparagus-ast",
|
||||
|
@ -2430,7 +2430,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "jsparagus-scope"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=ce731ef6014c41b1691a9be3480fbc43e5e9a396#ce731ef6014c41b1691a9be3480fbc43e5e9a396"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"jsparagus-ast",
|
||||
|
|
|
@ -160,6 +160,10 @@ class SmooshScriptStencil : public ScriptStencil {
|
|||
SmooshGCThing& item = result_.gcthings.data[i];
|
||||
|
||||
switch (item.kind) {
|
||||
case SmooshGCThingKind::AtomIndex: {
|
||||
gcThings.infallibleAppend(mozilla::AsVariant(allAtoms_[item.index]));
|
||||
break;
|
||||
}
|
||||
case SmooshGCThingKind::ScopeIndex: {
|
||||
gcThings.infallibleAppend(mozilla::AsVariant(ScopeIndex(item.index)));
|
||||
break;
|
||||
|
|
|
@ -12,12 +12,12 @@ log = "0.4"
|
|||
# Disable regex feature for code size.
|
||||
env_logger = {version = "0.6", default-features = false}
|
||||
# For non-jsparagus developers.
|
||||
jsparagus = { git = "https://github.com/mozilla-spidermonkey/jsparagus", rev = "9871d65530f5fc0e3d953efbf40b51e9c56c6d2a" }
|
||||
jsparagus = { git = "https://github.com/mozilla-spidermonkey/jsparagus", rev = "ce731ef6014c41b1691a9be3480fbc43e5e9a396" }
|
||||
# For local development, replace above with
|
||||
# jsparagus = { path = "{path to jsparagus}" }
|
||||
|
||||
[build-dependencies]
|
||||
# For non-jsparagus developers.
|
||||
jsparagus = { git = "https://github.com/mozilla-spidermonkey/jsparagus", rev = "9871d65530f5fc0e3d953efbf40b51e9c56c6d2a" }
|
||||
jsparagus = { git = "https://github.com/mozilla-spidermonkey/jsparagus", rev = "ce731ef6014c41b1691a9be3480fbc43e5e9a396" }
|
||||
# For local development, replace above with
|
||||
# jsparagus = { path = "{path to jsparagus}" }
|
||||
|
|
|
@ -69,6 +69,7 @@ pub struct SmooshCompileOptions {
|
|||
|
||||
#[repr(C)]
|
||||
pub enum SmooshGCThingKind {
|
||||
AtomIndex,
|
||||
ScopeIndex,
|
||||
RegExpIndex,
|
||||
}
|
||||
|
@ -82,6 +83,10 @@ pub struct SmooshGCThing {
|
|||
impl From<GCThing> for SmooshGCThing {
|
||||
fn from(item: GCThing) -> Self {
|
||||
match item {
|
||||
GCThing::Atom(index) => Self {
|
||||
kind: SmooshGCThingKind::AtomIndex,
|
||||
index: index.into(),
|
||||
},
|
||||
GCThing::Function(_index) => {
|
||||
panic!("Not yet implemented");
|
||||
}
|
||||
|
@ -211,7 +216,6 @@ pub struct SmooshResult {
|
|||
unimplemented: bool,
|
||||
error: CVec<u8>,
|
||||
bytecode: CVec<u8>,
|
||||
atoms: CVec<usize>,
|
||||
gcthings: CVec<SmooshGCThing>,
|
||||
scopes: CVec<SmooshScopeData>,
|
||||
scope_notes: CVec<SmooshScopeNote>,
|
||||
|
@ -277,7 +281,6 @@ impl SmooshResult {
|
|||
unimplemented,
|
||||
error,
|
||||
bytecode: CVec::empty(),
|
||||
atoms: CVec::empty(),
|
||||
gcthings: CVec::empty(),
|
||||
scopes: CVec::empty(),
|
||||
scope_notes: CVec::empty(),
|
||||
|
@ -344,7 +347,6 @@ pub unsafe extern "C" fn smoosh_run(
|
|||
let script = result.scripts.remove(0);
|
||||
|
||||
let bytecode = CVec::from(script.bytecode);
|
||||
let atoms = CVec::from(script.atoms.into_iter().map(|s| s.into()).collect());
|
||||
let gcthings = CVec::from(script.gcthings.into_iter().map(|x| x.into()).collect());
|
||||
let scopes = CVec::from(result.scopes.into_iter().map(|x| x.into()).collect());
|
||||
let scope_notes =
|
||||
|
@ -386,7 +388,6 @@ pub unsafe extern "C" fn smoosh_run(
|
|||
unimplemented: false,
|
||||
error: CVec::empty(),
|
||||
bytecode,
|
||||
atoms,
|
||||
gcthings,
|
||||
scopes,
|
||||
scope_notes,
|
||||
|
@ -543,7 +544,6 @@ pub unsafe extern "C" fn smoosh_get_slice_len_at(result: SmooshResult, index: us
|
|||
pub unsafe extern "C" fn smoosh_free(result: SmooshResult) {
|
||||
let _ = result.error.into();
|
||||
let _ = result.bytecode.into();
|
||||
let _ = result.atoms.into();
|
||||
let _ = result.gcthings.into();
|
||||
let _ = result.scopes.into();
|
||||
let _ = result.scope_notes.into();
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"2f0c8ec9fd1c91e102de4204892131106741e99885a7418c60eb894ed1a51b82","ast.json":"c4af9931cba29f6eb065783e63cbf21c57f065f4ef89245f874941be6f318238","generate_ast.py":"0c24431d9c07af42d7d17739c2e21465964151562437cfca093ceddde898bc93","src/arena.rs":"03ef07c963556160a6f1a85fd901833d7322f8a5f265c20d3e3543432dd2a96d","src/associated_data.rs":"028b7d2b370e75da153b50d86d9ff809e871d81a7fd3266e2d3727ce2bcc178d","src/dump_generated.rs":"23d594138b9e03e1e6d80972da3251ec10f8868cd385bfdd88b63ad761daeb94","src/json.rs":"ccc437c27f3fdaabb3d92b28eeb6bdee083bdf8014639ce09e7204a6529661a9","src/lib.rs":"b35553bedec9f6d88cc5194592f857dc13669559cbc8b206048c35299c4f86be","src/source_atom_set.rs":"1e6fb4be166c9fe4cf63ae6475f1abb12cb3dfa268250328a60f483a09e1481c","src/source_location.rs":"3832440ecec6de726262837072810410bddb45c075288386509511c153f6afd9","src/source_location_accessor_generated.rs":"80e8dd2221d73f6465778a9dfa0703ef84387520cc3dcfe4ba77870efc0c7ab3","src/source_slice_list.rs":"c82413b3081e091a3c4ce5d2c3624e54ecbeb0bb9952f10d373d10faf589955a","src/type_id_generated.rs":"c70cbdc0f84c2fd7e84fa6ef1614be22f63e52ffcbf2f93714c189dce3dad557","src/types_generated.rs":"ba04b36602c019a06b44ceab9d99707d91e7cc6fac051fd8db64ef65c71acdb3","src/visit_generated.rs":"98caf3e2305f648f5d31848cf6d7c7234f8c94b8b4b77a9bcd15fa4952eaca55"},"package":null}
|
||||
{"files":{"Cargo.toml":"2f0c8ec9fd1c91e102de4204892131106741e99885a7418c60eb894ed1a51b82","ast.json":"8bee02b419d90de0203ba7378aedecd5c94a447128b11231970119c9ecfecb77","generate_ast.py":"0c24431d9c07af42d7d17739c2e21465964151562437cfca093ceddde898bc93","src/arena.rs":"03ef07c963556160a6f1a85fd901833d7322f8a5f265c20d3e3543432dd2a96d","src/associated_data.rs":"028b7d2b370e75da153b50d86d9ff809e871d81a7fd3266e2d3727ce2bcc178d","src/dump_generated.rs":"a1368d31a8e3d286f230058e4a007ce7cd94240f2e59c0cc31c8a56756b1c1b3","src/json.rs":"ccc437c27f3fdaabb3d92b28eeb6bdee083bdf8014639ce09e7204a6529661a9","src/lib.rs":"b35553bedec9f6d88cc5194592f857dc13669559cbc8b206048c35299c4f86be","src/source_atom_set.rs":"1e6fb4be166c9fe4cf63ae6475f1abb12cb3dfa268250328a60f483a09e1481c","src/source_location.rs":"3832440ecec6de726262837072810410bddb45c075288386509511c153f6afd9","src/source_location_accessor_generated.rs":"4a016e4860a2b6b9b7637dff10c634255f6c1942231eb75224261679944fa169","src/source_slice_list.rs":"c82413b3081e091a3c4ce5d2c3624e54ecbeb0bb9952f10d373d10faf589955a","src/type_id_generated.rs":"c70cbdc0f84c2fd7e84fa6ef1614be22f63e52ffcbf2f93714c189dce3dad557","src/types_generated.rs":"965e0619315156b9fd918f26f6317aa98970b535a7df7442f163b23ee5eaf641","src/visit_generated.rs":"d09510127771be0c3a20c95ed48a4e4d387144e6cb08b02783a81739539111ed"},"package":null}
|
|
@ -35,6 +35,9 @@
|
|||
},
|
||||
"CompoundAssignmentOperator": {
|
||||
"_type": "enum",
|
||||
"LogicalOr": null,
|
||||
"LogicalAnd": null,
|
||||
"Coalesce": null,
|
||||
"Add": null,
|
||||
"Sub": null,
|
||||
"Mul": null,
|
||||
|
|
|
@ -140,6 +140,15 @@ impl<'alloc> ASTDump for CompoundAssignmentOperator {
|
|||
where W: io::Write
|
||||
{
|
||||
match self {
|
||||
CompoundAssignmentOperator::LogicalOr { .. } => {
|
||||
write!(out, "LogicalOr").expect("failed to dump");
|
||||
}
|
||||
CompoundAssignmentOperator::LogicalAnd { .. } => {
|
||||
write!(out, "LogicalAnd").expect("failed to dump");
|
||||
}
|
||||
CompoundAssignmentOperator::Coalesce { .. } => {
|
||||
write!(out, "Coalesce").expect("failed to dump");
|
||||
}
|
||||
CompoundAssignmentOperator::Add { .. } => {
|
||||
write!(out, "Add").expect("failed to dump");
|
||||
}
|
||||
|
|
|
@ -606,6 +606,18 @@ impl<'alloc> SourceLocationAccessor for ClassExpression<'alloc> {
|
|||
impl<'alloc> SourceLocationAccessor for CompoundAssignmentOperator {
|
||||
fn set_loc(&mut self, start: SourceLocation, end: SourceLocation) {
|
||||
match self {
|
||||
CompoundAssignmentOperator::LogicalOr { mut loc } => {
|
||||
loc.start = start.start;
|
||||
loc.end = end.end;
|
||||
}
|
||||
CompoundAssignmentOperator::LogicalAnd { mut loc } => {
|
||||
loc.start = start.start;
|
||||
loc.end = end.end;
|
||||
}
|
||||
CompoundAssignmentOperator::Coalesce { mut loc } => {
|
||||
loc.start = start.start;
|
||||
loc.end = end.end;
|
||||
}
|
||||
CompoundAssignmentOperator::Add { mut loc } => {
|
||||
loc.start = start.start;
|
||||
loc.end = end.end;
|
||||
|
@ -659,6 +671,15 @@ impl<'alloc> SourceLocationAccessor for CompoundAssignmentOperator {
|
|||
|
||||
fn get_loc(&self) -> SourceLocation {
|
||||
match self {
|
||||
CompoundAssignmentOperator::LogicalOr { loc } => {
|
||||
*loc
|
||||
}
|
||||
CompoundAssignmentOperator::LogicalAnd { loc } => {
|
||||
*loc
|
||||
}
|
||||
CompoundAssignmentOperator::Coalesce { loc } => {
|
||||
*loc
|
||||
}
|
||||
CompoundAssignmentOperator::Add { loc } => {
|
||||
*loc
|
||||
}
|
||||
|
|
|
@ -60,6 +60,15 @@ pub enum VariableDeclarationKind {
|
|||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum CompoundAssignmentOperator {
|
||||
LogicalOr {
|
||||
loc: SourceLocation,
|
||||
},
|
||||
LogicalAnd {
|
||||
loc: SourceLocation,
|
||||
},
|
||||
Coalesce {
|
||||
loc: SourceLocation,
|
||||
},
|
||||
Add {
|
||||
loc: SourceLocation,
|
||||
},
|
||||
|
|
|
@ -164,6 +164,15 @@ pub trait Pass<'alloc> {
|
|||
fn visit_compound_assignment_operator(&mut self, ast: &'alloc CompoundAssignmentOperator) {
|
||||
self.enter_compound_assignment_operator(ast);
|
||||
match ast {
|
||||
CompoundAssignmentOperator::LogicalOr { .. } => {
|
||||
self.visit_enum_compound_assignment_operator_variant_logical_or()
|
||||
}
|
||||
CompoundAssignmentOperator::LogicalAnd { .. } => {
|
||||
self.visit_enum_compound_assignment_operator_variant_logical_and()
|
||||
}
|
||||
CompoundAssignmentOperator::Coalesce { .. } => {
|
||||
self.visit_enum_compound_assignment_operator_variant_coalesce()
|
||||
}
|
||||
CompoundAssignmentOperator::Add { .. } => {
|
||||
self.visit_enum_compound_assignment_operator_variant_add()
|
||||
}
|
||||
|
@ -210,6 +219,15 @@ pub trait Pass<'alloc> {
|
|||
fn leave_compound_assignment_operator(&mut self, ast: &'alloc CompoundAssignmentOperator) {
|
||||
}
|
||||
|
||||
fn visit_enum_compound_assignment_operator_variant_logical_or(&mut self) {
|
||||
}
|
||||
|
||||
fn visit_enum_compound_assignment_operator_variant_logical_and(&mut self) {
|
||||
}
|
||||
|
||||
fn visit_enum_compound_assignment_operator_variant_coalesce(&mut self) {
|
||||
}
|
||||
|
||||
fn visit_enum_compound_assignment_operator_variant_add(&mut self) {
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"44e966f17baf603f83e2c5ea05563744d1d564471a837ff025218c65c5de0b93","scripts/update_opcodes.py":"4b22ead637282b644020ea45aa20d93ba86dec0d1231f8edcd9a0ed1e5fa01e5","src/array_emitter.rs":"bbc6528321f1d11d7c86c4f2bfdcfc9dced8f0b8b1c30c9f0a5355f300d196b6","src/ast_emitter.rs":"937c4609b452dde38f2b5b92aad1c7ee2ed7b1b54eff7b8ce408c52b3e5aa713","src/block_emitter.rs":"a95e553b667990fb585d4186588b0b976a5a477649ab7b9ddf01b26a3ddc5918","src/bytecode_offset.rs":"2aa7ba8c3cfbbd832092e65b599ab1c5a28d784ccc65d9e351bba656421b9a69","src/compilation_info.rs":"259d16ed7580c973cc0bb24a1ff4c9e8a3ca37aab328d946aa7deeb832d46b4f","src/control_structures.rs":"36a5f050b7a5d9c46d18a83f36b23ce0aca8224aff690fdd652e8fab2ef7eb34","src/copy/AsyncFunctionResolveKind.h":"3851ecbb4728257595dd6e900749d1d8e02558574c00424a7ff0e3ca007fa6ec","src/copy/BytecodeFormatFlags.h":"7dc2932321cf7cf874cd92b6d8076ebd4139492730f3ee5a3b6ed7fc57a0c685","src/copy/CheckIsCallableKind.h":"66556f922d403cb46d4ad03a97a6795bcf22505eb9733cbfacd3f2cdd5f39463","src/copy/CheckIsObjectKind.h":"8f0e112396d966c9221a743d353f62671e04cdace7dd49a59898d94ba0f621b7","src/copy/FunctionFlags.h":"4376653f70711d916bc36c2096165f0be9a50c487b9d471821da1cad80daa3a3","src/copy/FunctionPrefixKind.h":"f540a5c646a519b2d61aa27e4be865e08a31438def00ad5ba4ba2982ad1f2275","src/copy/GeneratorAndAsyncKind.h":"301668ce705970a51abfa94f89fd5db29ef5f129525110860e9e9bf7586ef187","src/copy/GeneratorResumeKind.h":"9e3cd9dc9c7f50937c6c45d73ec092dbfd92c4b56818ae6d1504bcd77078d0a6","src/copy/Opcodes.h":"72e0faa4eb0ed4e59ee2205d0ed6734fc4e7383552545d605eef2201e69d4c99","src/copy/SourceNotes.h":"1e467f4e63d6f40a428e257fecd210bd14664516adf75a45cb17ab02ccd65fd8","src/copy/StencilEnums.h":"1c4d1a2c8b365c5dd01bbf09e921a0ef73f5614e5bfb1551cd7147def92ecdf9","src/copy/Symbol.h":"f68b32e1b7add89931a1fa82a6888ebf6d875d03b05872469de426844532bf33","src/copy/ThrowMsgKind.h":"da805756961d81a2b50aeb391a02fd59a0aa39a9e3eb6aae21b423b15875ab30","src/dis.rs":"945acee8fce373f160bdd53f538bcc97037eaade0029996c9c9cbda980c65205","src/emitter.rs":"c81b0f109e4b6f14778cd6ee23ca32f78f7e5bec7d6898de7b5f70fdce944bd3","src/emitter_scope.rs":"71c0621d5e58987916b1854d24ca8b8f10296b37000122e28ecac71bf6badcb8","src/expression_emitter.rs":"f8e02785dffb179bbe9fe58e45bbfccc08adc3ad0a071a0073bed0feedc8ed9a","src/function.rs":"2fe396b0ad3e1b73854ba8feff37353fe5986732868490c8ba1dfc51a4074f06","src/gcthings.rs":"7441b4a04ed56204682e3d328b2f87c25a3dacaab7b76011b521a4fc792ab6e9","src/lib.rs":"361ca4f6eff158ab18f5d765ec09cd9428590e84e59f9a0c7d219f5eea763904","src/object_emitter.rs":"1d3acaca4ec595473c0d31060dbab22eaaca7a02d76aa2e0d9c550541cdccdf1","src/opcode.rs":"4434a36d70387c5897f3349361e0010be08cf9d9499b47b22c0b4dbdb2ad4522","src/opcode_info.rs":"3475f87581ce05c301b915aca584577d15df3e1d7d4096c31546462d4ee1ece5","src/reference_op_emitter.rs":"8b5b3974830bcf77e78c96112522404a2edae21c5961c8386e70dc841709a100","src/regexp.rs":"7436cf545b990bec7dcc51ff28d67deaca9d4ce894468fdad0dd44b25c571cf2","src/scope_notes.rs":"e0861d8db2fae3410c3711fe3beb42b67faf90a49cb5f06ed40025a6b5ed6db5","src/script_atom_set.rs":"8a567a786c6cc15192ca629deb3544546ec204efd1d05d16ff9ccdbf42a94e96","src/script_emitter.rs":"44a6be5ecdcde3c32d78d100a205d38be2591c7c2cc109967579af7393e09fe8","src/stencil.rs":"38043a6eeb3e6b02010e98c49f88001516a1b7340eb976d2d3c175794e1c5b84"},"package":null}
|
||||
{"files":{"Cargo.toml":"44e966f17baf603f83e2c5ea05563744d1d564471a837ff025218c65c5de0b93","scripts/update_opcodes.py":"5db429c128f8dfe67218f6097c0ebfce31dc0e0403e21453766216e35fdf9625","src/array_emitter.rs":"bbc6528321f1d11d7c86c4f2bfdcfc9dced8f0b8b1c30c9f0a5355f300d196b6","src/ast_emitter.rs":"3664a7417328e1bb400e6cc0e6a0a8b916068c67036aadb0d0616340518eee1a","src/block_emitter.rs":"a95e553b667990fb585d4186588b0b976a5a477649ab7b9ddf01b26a3ddc5918","src/bytecode_offset.rs":"2aa7ba8c3cfbbd832092e65b599ab1c5a28d784ccc65d9e351bba656421b9a69","src/compilation_info.rs":"259d16ed7580c973cc0bb24a1ff4c9e8a3ca37aab328d946aa7deeb832d46b4f","src/control_structures.rs":"6c746f18d6f84859ba1989635f343307acad4982f1e0b94092d2473a5ad451d4","src/copy/AsyncFunctionResolveKind.h":"3851ecbb4728257595dd6e900749d1d8e02558574c00424a7ff0e3ca007fa6ec","src/copy/BytecodeFormatFlags.h":"7dc2932321cf7cf874cd92b6d8076ebd4139492730f3ee5a3b6ed7fc57a0c685","src/copy/CheckIsCallableKind.h":"66556f922d403cb46d4ad03a97a6795bcf22505eb9733cbfacd3f2cdd5f39463","src/copy/CheckIsObjectKind.h":"8f0e112396d966c9221a743d353f62671e04cdace7dd49a59898d94ba0f621b7","src/copy/FunctionFlags.h":"4376653f70711d916bc36c2096165f0be9a50c487b9d471821da1cad80daa3a3","src/copy/FunctionPrefixKind.h":"f540a5c646a519b2d61aa27e4be865e08a31438def00ad5ba4ba2982ad1f2275","src/copy/GeneratorAndAsyncKind.h":"301668ce705970a51abfa94f89fd5db29ef5f129525110860e9e9bf7586ef187","src/copy/GeneratorResumeKind.h":"9e3cd9dc9c7f50937c6c45d73ec092dbfd92c4b56818ae6d1504bcd77078d0a6","src/copy/Opcodes.h":"72e0faa4eb0ed4e59ee2205d0ed6734fc4e7383552545d605eef2201e69d4c99","src/copy/SourceNotes.h":"1e467f4e63d6f40a428e257fecd210bd14664516adf75a45cb17ab02ccd65fd8","src/copy/StencilEnums.h":"1c4d1a2c8b365c5dd01bbf09e921a0ef73f5614e5bfb1551cd7147def92ecdf9","src/copy/Symbol.h":"f68b32e1b7add89931a1fa82a6888ebf6d875d03b05872469de426844532bf33","src/copy/ThrowMsgKind.h":"da805756961d81a2b50aeb391a02fd59a0aa39a9e3eb6aae21b423b15875ab30","src/dis.rs":"4da6c62ce04093d0deda035c1cf4289e026fb6c1aab1b11ff4c0542b84d219b2","src/emitter.rs":"72338bd777152fec3f7e49d6e399a3aafa7ffbb7ffd4643d94579aa36ba71cd1","src/emitter_scope.rs":"481139d52dcac11dbc75e91c5b815943545e959378e29ec4699b083323a1b399","src/expression_emitter.rs":"f8e02785dffb179bbe9fe58e45bbfccc08adc3ad0a071a0073bed0feedc8ed9a","src/function.rs":"5866f0a5d41b6bfa8f7d205cafcc2a3c2a20facdab4b98a1bd6c8c474dc82ad3","src/function_declaration_emitter.rs":"c75c4986322f98f870fb70ab1bea29321ad76a1c36555bcd8cfee7b7c79145ac","src/gcthings.rs":"1513cf94c0ceb002708f6a2ba6c642ae244763b708eb42991855d33c730290ef","src/lib.rs":"335e0e26909313b094a59c05c27ccdb69fc7fa7a51a45cc15bd7522b094bd3e2","src/object_emitter.rs":"998423b3d6ef8797fadef6763803627df72fde292b1b34d6a41b2e66a331a181","src/opcode.rs":"4434a36d70387c5897f3349361e0010be08cf9d9499b47b22c0b4dbdb2ad4522","src/opcode_info.rs":"3475f87581ce05c301b915aca584577d15df3e1d7d4096c31546462d4ee1ece5","src/reference_op_emitter.rs":"753c25b3ae16613b7e0efb3c79637d62ef4c61f54ee64c83c5f694d331a609e3","src/regexp.rs":"7436cf545b990bec7dcc51ff28d67deaca9d4ce894468fdad0dd44b25c571cf2","src/scope_notes.rs":"9947ba5aba3097321c76adcb5648a478e4a67e088fdc1e01511e51c4ad41a9f3","src/script_emitter.rs":"44a6be5ecdcde3c32d78d100a205d38be2591c7c2cc109967579af7393e09fe8","src/stencil.rs":"d578398c6c211f88fd932545b482eb13c5692dc4b2c919e64c202b7b2e411274"},"package":null}
|
|
@ -349,10 +349,10 @@ def extract_function_types(paths):
|
|||
types = {}
|
||||
|
||||
extract_enum(types, paths, 'FunctionKind', filename='FunctionFlags.h')
|
||||
extract_enum(types, paths, 'GeneratorKind',
|
||||
filename='GeneratorAndAsyncKind.h')
|
||||
extract_enum(types, paths, 'FunctionAsyncKind',
|
||||
filename='GeneratorAndAsyncKind.h')
|
||||
#extract_enum(types, paths, 'GeneratorKind',
|
||||
# filename='GeneratorAndAsyncKind.h')
|
||||
#extract_enum(types, paths, 'FunctionAsyncKind',
|
||||
# filename='GeneratorAndAsyncKind.h')
|
||||
|
||||
return types
|
||||
|
||||
|
@ -438,7 +438,7 @@ def parse_operands(opcode):
|
|||
|
||||
if 'JOF_ATOM' in opcode.format_:
|
||||
assert ty == 'u32'
|
||||
ty = 'ScriptAtomSetIndex'
|
||||
ty = 'GCThingIndex'
|
||||
|
||||
if 'JOF_ICINDEX' in opcode.format_ or 'JOF_LOOPHEAD' in opcode.format_:
|
||||
if ty == 'u32' and name == 'ic_index':
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::compilation_info::CompilationInfo;
|
|||
use crate::emitter::{EmitError, EmitOptions, InstructionWriter};
|
||||
use crate::emitter_scope::{EmitterScopeStack, NameLocation};
|
||||
use crate::expression_emitter::*;
|
||||
use crate::function_declaration_emitter::{DummyFunctionScriptEmitter, FunctionDeclarationEmitter};
|
||||
use crate::object_emitter::*;
|
||||
use crate::opcode::Opcode;
|
||||
use crate::reference_op_emitter::{
|
||||
|
@ -20,6 +21,7 @@ use crate::script_emitter::ScriptEmitter;
|
|||
use crate::stencil::{EmitResult, ScriptStencilIndex, ScriptStencilList};
|
||||
use ast::source_atom_set::{CommonSourceAtomSetIndices, SourceAtomSetIndex};
|
||||
use ast::types::*;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::control_structures::{
|
||||
BreakEmitter, CForEmitter, ContinueEmitter, ControlStructureStack, DoWhileEmitter,
|
||||
|
@ -54,6 +56,10 @@ pub struct AstEmitter<'alloc, 'opt> {
|
|||
pub compilation_info: &'opt mut CompilationInfo<'alloc>,
|
||||
pub scripts: &'opt mut ScriptStencilList,
|
||||
pub control_stack: ControlStructureStack,
|
||||
|
||||
/// Holds the offset of top-level function declarations, to check if the
|
||||
/// given function function declaration is top-level.
|
||||
top_level_function_offsets: HashSet<usize>,
|
||||
}
|
||||
|
||||
impl<'alloc, 'opt> AstEmitter<'alloc, 'opt> {
|
||||
|
@ -69,14 +75,40 @@ impl<'alloc, 'opt> AstEmitter<'alloc, 'opt> {
|
|||
compilation_info,
|
||||
scripts,
|
||||
control_stack: ControlStructureStack::new(),
|
||||
top_level_function_offsets: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_inner<ScriptFn>(
|
||||
&mut self,
|
||||
callback: ScriptFn,
|
||||
) -> Result<ScriptStencilIndex, EmitError>
|
||||
where
|
||||
ScriptFn: Fn(&mut AstEmitter) -> Result<(), EmitError>,
|
||||
{
|
||||
let script_index = self.scripts.allocate();
|
||||
|
||||
let inner_script = {
|
||||
let mut inner_emitter =
|
||||
AstEmitter::new(self.options, self.compilation_info, self.scripts);
|
||||
|
||||
callback(&mut inner_emitter)?;
|
||||
|
||||
inner_emitter.emit.into()
|
||||
};
|
||||
|
||||
self.scripts.populate(script_index, inner_script);
|
||||
|
||||
Ok(script_index)
|
||||
}
|
||||
|
||||
pub fn lookup_name(&mut self, name: SourceAtomSetIndex) -> NameLocation {
|
||||
self.scope_stack.lookup_name(name)
|
||||
}
|
||||
|
||||
fn emit_script(mut self, ast: &Script) -> Result<ScriptStencilIndex, EmitError> {
|
||||
let script_index = self.scripts.allocate();
|
||||
|
||||
let scope_data_map = &self.compilation_info.scope_data_map;
|
||||
let function_map = &self.compilation_info.function_map;
|
||||
|
||||
|
@ -89,6 +121,10 @@ impl<'alloc, 'opt> AstEmitter<'alloc, 'opt> {
|
|||
.map(|key| *function_map.get(key).expect("function should exist"))
|
||||
.collect();
|
||||
|
||||
for fun in &top_level_functions {
|
||||
self.note_top_level_function(fun);
|
||||
}
|
||||
|
||||
ScriptEmitter {
|
||||
top_level_functions: top_level_functions.iter(),
|
||||
top_level_function: |emitter, fun| emitter.emit_top_level_function_declaration(fun),
|
||||
|
@ -97,20 +133,24 @@ impl<'alloc, 'opt> AstEmitter<'alloc, 'opt> {
|
|||
}
|
||||
.emit(&mut self)?;
|
||||
|
||||
Ok(self.scripts.push(self.emit.into()))
|
||||
self.scripts.populate(script_index, self.emit.into());
|
||||
|
||||
Ok(script_index)
|
||||
}
|
||||
|
||||
fn emit_top_level_function_declaration(&mut self, fun: &Function) -> Result<(), EmitError> {
|
||||
let _name = fun
|
||||
let name = fun
|
||||
.name
|
||||
.as_ref()
|
||||
.expect("function declaration should have name")
|
||||
.name
|
||||
.value;
|
||||
|
||||
Err(EmitError::NotImplemented(
|
||||
"TODO: top level FunctionDeclaration",
|
||||
))
|
||||
let fun_index = DummyFunctionScriptEmitter { name }.emit(self)?;
|
||||
|
||||
FunctionDeclarationEmitter { fun: fun_index }.emit(self);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_statement(&mut self, ast: &Statement) -> Result<(), EmitError> {
|
||||
|
@ -128,29 +168,22 @@ impl<'alloc, 'opt> AstEmitter<'alloc, 'opt> {
|
|||
}
|
||||
Statement::BreakStatement { label, .. } => {
|
||||
BreakEmitter {
|
||||
jump: JumpKind::Goto,
|
||||
label: label.as_ref().map(|x| x.value),
|
||||
}
|
||||
.emit(self);
|
||||
return Err(EmitError::NotImplemented(
|
||||
"TODO: scope handling for BreakStatement",
|
||||
));
|
||||
}
|
||||
Statement::ContinueStatement { label, .. } => {
|
||||
ContinueEmitter {
|
||||
jump: JumpKind::Goto,
|
||||
label: label.as_ref().map(|x| x.value),
|
||||
}
|
||||
.emit(self);
|
||||
return Err(EmitError::NotImplemented(
|
||||
"TODO: scope handling for ContinueStatement",
|
||||
));
|
||||
}
|
||||
Statement::DebuggerStatement { .. } => {
|
||||
return Err(EmitError::NotImplemented("TODO: DebuggerStatement"));
|
||||
}
|
||||
Statement::DoWhileStatement { block, test, .. } => {
|
||||
DoWhileEmitter {
|
||||
enclosing_emitter_scope_depth: self.scope_stack.current_depth(),
|
||||
block: |emitter| emitter.emit_statement(block),
|
||||
test: |emitter| emitter.emit_expression(test),
|
||||
}
|
||||
|
@ -177,6 +210,7 @@ impl<'alloc, 'opt> AstEmitter<'alloc, 'opt> {
|
|||
..
|
||||
} => {
|
||||
CForEmitter {
|
||||
enclosing_emitter_scope_depth: self.scope_stack.current_depth(),
|
||||
maybe_init: init,
|
||||
maybe_test: test,
|
||||
maybe_update: update,
|
||||
|
@ -205,6 +239,7 @@ impl<'alloc, 'opt> AstEmitter<'alloc, 'opt> {
|
|||
}
|
||||
Statement::LabelledStatement { label, body, .. } => {
|
||||
LabelEmitter {
|
||||
enclosing_emitter_scope_depth: self.scope_stack.current_depth(),
|
||||
name: label.value,
|
||||
body: |emitter| emitter.emit_statement(body),
|
||||
}
|
||||
|
@ -236,6 +271,7 @@ impl<'alloc, 'opt> AstEmitter<'alloc, 'opt> {
|
|||
}
|
||||
Statement::WhileStatement { test, block, .. } => {
|
||||
WhileEmitter {
|
||||
enclosing_emitter_scope_depth: self.scope_stack.current_depth(),
|
||||
test: |emitter| emitter.emit_expression(test),
|
||||
block: |emitter| emitter.emit_statement(block),
|
||||
}
|
||||
|
@ -244,14 +280,26 @@ impl<'alloc, 'opt> AstEmitter<'alloc, 'opt> {
|
|||
Statement::WithStatement { .. } => {
|
||||
return Err(EmitError::NotImplemented("TODO: WithStatement"));
|
||||
}
|
||||
Statement::FunctionDeclaration(_) => {
|
||||
return Err(EmitError::NotImplemented("TODO: FunctionDeclaration"));
|
||||
Statement::FunctionDeclaration(fun) => {
|
||||
if !self.is_top_level_function(fun) {
|
||||
return Err(EmitError::NotImplemented(
|
||||
"TODO: non-top-level FunctionDeclaration",
|
||||
));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn note_top_level_function(&mut self, fun: &Function) {
|
||||
self.top_level_function_offsets.insert(fun.loc.start);
|
||||
}
|
||||
|
||||
fn is_top_level_function(&self, fun: &Function) -> bool {
|
||||
self.top_level_function_offsets.contains(&fun.loc.start)
|
||||
}
|
||||
|
||||
fn emit_variable_declaration_statement(
|
||||
&mut self,
|
||||
ast: &VariableDeclaration,
|
||||
|
@ -376,7 +424,7 @@ impl<'alloc, 'opt> AstEmitter<'alloc, 'opt> {
|
|||
}
|
||||
|
||||
Expression::LiteralStringExpression { value, .. } => {
|
||||
let str_index = self.emit.get_atom_index(*value);
|
||||
let str_index = self.emit.get_atom_gcthing_index(*value);
|
||||
self.emit.string(str_index);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::ast_emitter::AstEmitter;
|
|||
use crate::bytecode_offset::{BytecodeOffset, BytecodeOffsetDiff};
|
||||
use crate::emitter::EmitError;
|
||||
use crate::emitter::InstructionWriter;
|
||||
use crate::emitter_scope::EmitterScopeDepth;
|
||||
use ast::source_atom_set::SourceAtomSetIndex;
|
||||
|
||||
// Control structures
|
||||
|
@ -122,7 +123,9 @@ pub trait Continuable {
|
|||
fn emit_continue_target_and_patch(&mut self, emit: &mut InstructionWriter);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct LoopControl {
|
||||
enclosing_emitter_scope_depth: EmitterScopeDepth,
|
||||
breaks: Vec<BytecodeOffset>,
|
||||
continues: Vec<BytecodeOffset>,
|
||||
head: BytecodeOffset,
|
||||
|
@ -153,9 +156,14 @@ impl Continuable for LoopControl {
|
|||
}
|
||||
|
||||
impl LoopControl {
|
||||
pub fn new(emit: &mut InstructionWriter, depth: u8) -> Self {
|
||||
pub fn new(
|
||||
emit: &mut InstructionWriter,
|
||||
depth: u8,
|
||||
enclosing_emitter_scope_depth: EmitterScopeDepth,
|
||||
) -> Self {
|
||||
let offset = LoopControl::open_loop(emit, depth);
|
||||
Self {
|
||||
enclosing_emitter_scope_depth,
|
||||
breaks: Vec::new(),
|
||||
continues: Vec::new(),
|
||||
head: offset,
|
||||
|
@ -184,8 +192,9 @@ impl LoopControl {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct LabelControl {
|
||||
enclosing_emitter_scope_depth: EmitterScopeDepth,
|
||||
name: SourceAtomSetIndex,
|
||||
breaks: Vec<BytecodeOffset>,
|
||||
head: BytecodeOffset,
|
||||
|
@ -199,14 +208,21 @@ impl Breakable for LabelControl {
|
|||
}
|
||||
|
||||
fn emit_break_target_and_patch(&mut self, emit: &mut InstructionWriter) {
|
||||
emit.emit_jump_target_and_patch(&self.breaks);
|
||||
if !self.breaks.is_empty() {
|
||||
emit.emit_jump_target_and_patch(&self.breaks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LabelControl {
|
||||
pub fn new(name: SourceAtomSetIndex, emit: &mut InstructionWriter) -> Self {
|
||||
pub fn new(
|
||||
name: SourceAtomSetIndex,
|
||||
emit: &mut InstructionWriter,
|
||||
enclosing_emitter_scope_depth: EmitterScopeDepth,
|
||||
) -> Self {
|
||||
let offset = emit.bytecode_offset();
|
||||
Self {
|
||||
enclosing_emitter_scope_depth,
|
||||
name,
|
||||
head: offset,
|
||||
breaks: Vec::new(),
|
||||
|
@ -214,11 +230,21 @@ impl LabelControl {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Control {
|
||||
Loop(LoopControl),
|
||||
Label(LabelControl),
|
||||
}
|
||||
|
||||
impl Control {
|
||||
fn enclosing_emitter_scope_depth(&self) -> EmitterScopeDepth {
|
||||
match self {
|
||||
Control::Loop(control) => control.enclosing_emitter_scope_depth,
|
||||
Control::Label(control) => control.enclosing_emitter_scope_depth,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compared to C++ impl, this uses explicit stack struct,
|
||||
// given Rust cannot store a reference of stack-allocated object into
|
||||
// another object that has longer-lifetime.
|
||||
|
@ -233,21 +259,31 @@ impl ControlStructureStack {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn open_loop(&mut self, emit: &mut InstructionWriter) {
|
||||
pub fn open_loop(
|
||||
&mut self,
|
||||
emit: &mut InstructionWriter,
|
||||
enclosing_emitter_scope_depth: EmitterScopeDepth,
|
||||
) {
|
||||
let depth = (self.control_stack.len() + 1) as u8;
|
||||
|
||||
let new_loop = Control::Loop(LoopControl::new(emit, depth));
|
||||
let new_loop = Control::Loop(LoopControl::new(emit, depth, enclosing_emitter_scope_depth));
|
||||
|
||||
self.control_stack.push(new_loop);
|
||||
}
|
||||
|
||||
pub fn open_label(&mut self, name: SourceAtomSetIndex, emit: &mut InstructionWriter) {
|
||||
let new_label = LabelControl::new(name, emit);
|
||||
pub fn open_label(
|
||||
&mut self,
|
||||
name: SourceAtomSetIndex,
|
||||
emit: &mut InstructionWriter,
|
||||
enclosing_emitter_scope_depth: EmitterScopeDepth,
|
||||
) {
|
||||
let new_label = LabelControl::new(name, emit, enclosing_emitter_scope_depth);
|
||||
self.control_stack.push(Control::Label(new_label));
|
||||
}
|
||||
|
||||
pub fn register_break(&mut self, offset: BytecodeOffset) {
|
||||
let innermost = self.innermost();
|
||||
|
||||
match innermost {
|
||||
Control::Label(control) => control.register_break(offset),
|
||||
Control::Loop(control) => control.register_break(offset),
|
||||
|
@ -265,12 +301,9 @@ impl ControlStructureStack {
|
|||
}
|
||||
|
||||
pub fn register_labelled_break(&mut self, label: SourceAtomSetIndex, offset: BytecodeOffset) {
|
||||
if let Some(control) = self.find_labelled_loop(label) {
|
||||
control.register_break(offset);
|
||||
} else {
|
||||
panic!(
|
||||
"A labelled break was passed, but no label was found. This should be caught by early errors"
|
||||
)
|
||||
match self.find_labelled_control(label) {
|
||||
Control::Label(control) => control.register_break(offset),
|
||||
Control::Loop(control) => control.register_break(offset),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,7 +322,7 @@ impl ControlStructureStack {
|
|||
}
|
||||
|
||||
pub fn find_labelled_loop(&mut self, label: SourceAtomSetIndex) -> Option<&mut LoopControl> {
|
||||
let label_index = self.find_labelled_index(label)?;
|
||||
let label_index = self.find_labelled_index(label);
|
||||
// To find the associated loop for a label, we can take the label's index + 1, as the
|
||||
// associated loop should always be in the position after the label.
|
||||
let control = self.control_stack.get_mut(label_index + 1);
|
||||
|
@ -299,16 +332,34 @@ impl ControlStructureStack {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_labelled_index(&mut self, label: SourceAtomSetIndex) -> Option<usize> {
|
||||
self.control_stack.iter().position(|control| match control {
|
||||
Control::Label(control) => {
|
||||
if control.name == label {
|
||||
return true;
|
||||
pub fn find_labelled_control(&mut self, label: SourceAtomSetIndex) -> &mut Control {
|
||||
self.control_stack
|
||||
.iter_mut()
|
||||
.find(|control| match control {
|
||||
Control::Label(control) => {
|
||||
if control.name == label {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
false
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
_ => false,
|
||||
})
|
||||
.expect("there should be a control with this label")
|
||||
}
|
||||
|
||||
pub fn find_labelled_index(&mut self, label: SourceAtomSetIndex) -> usize {
|
||||
self.control_stack
|
||||
.iter()
|
||||
.position(|control| match control {
|
||||
Control::Label(control) => {
|
||||
if control.name == label {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
.expect("there should be a control with this label")
|
||||
}
|
||||
|
||||
pub fn emit_continue_target_and_patch(&mut self, emit: &mut InstructionWriter) {
|
||||
|
@ -353,74 +404,74 @@ impl ControlStructureStack {
|
|||
}
|
||||
}
|
||||
|
||||
// Struct for multiple jumps that point to the same target. Examples are breaks and loop conditions.
|
||||
pub struct BreakEmitter {
|
||||
pub jump: JumpKind,
|
||||
pub label: Option<SourceAtomSetIndex>,
|
||||
struct RegisteredJump<F1>
|
||||
where
|
||||
F1: Fn(&mut AstEmitter, BytecodeOffset),
|
||||
{
|
||||
kind: JumpKind,
|
||||
// This callback registers the bytecode offset of the jump in a list of bytecode offsets
|
||||
// associated with a loop or a label.
|
||||
register_offset: F1,
|
||||
}
|
||||
|
||||
impl Jump for BreakEmitter {
|
||||
impl<F1> Jump for RegisteredJump<F1>
|
||||
where
|
||||
F1: Fn(&mut AstEmitter, BytecodeOffset),
|
||||
{
|
||||
fn jump_kind(&mut self) -> &JumpKind {
|
||||
&self.jump
|
||||
&self.kind
|
||||
}
|
||||
}
|
||||
|
||||
impl<F1> RegisteredJump<F1>
|
||||
where
|
||||
F1: Fn(&mut AstEmitter, BytecodeOffset),
|
||||
{
|
||||
pub fn emit(&mut self, emitter: &mut AstEmitter) {
|
||||
let offset = emitter.emit.bytecode_offset();
|
||||
self.emit_jump(emitter);
|
||||
(self.register_offset)(emitter, offset);
|
||||
}
|
||||
}
|
||||
|
||||
// Struct for multiple jumps that point to the same target. Examples are breaks and loop conditions.
|
||||
pub struct BreakEmitter {
|
||||
pub label: Option<SourceAtomSetIndex>,
|
||||
}
|
||||
|
||||
impl BreakEmitter {
|
||||
pub fn emit(&mut self, emitter: &mut AstEmitter) {
|
||||
// TODO: For 'break' statements in non local loops, we need to emit some extra bytecode.
|
||||
// see https://searchfox.org/mozilla-central/rev/a707541ff423ade0d81cef6488e6ecfa09273886/js/src/frontend/BytecodeEmitter.cpp#702-840
|
||||
let offset = emitter.emit.bytecode_offset();
|
||||
match self.label {
|
||||
Some(label) => emitter.control_stack.register_labelled_break(label, offset),
|
||||
None => emitter.control_stack.register_break(offset),
|
||||
NonLocalExitControl {
|
||||
registered_jump: RegisteredJump {
|
||||
kind: JumpKind::Goto,
|
||||
register_offset: |emitter, offset| match self.label {
|
||||
Some(label) => emitter.control_stack.register_labelled_break(label, offset),
|
||||
None => emitter.control_stack.register_break(offset),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
self.emit_jump(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
// Struct for multiple jumps that point to the same target. Examples are breaks and loop conditions.
|
||||
pub struct InternalBreakEmitter {
|
||||
pub jump: JumpKind,
|
||||
}
|
||||
|
||||
impl Jump for InternalBreakEmitter {
|
||||
fn jump_kind(&mut self) -> &JumpKind {
|
||||
&self.jump
|
||||
}
|
||||
}
|
||||
|
||||
impl InternalBreakEmitter {
|
||||
pub fn emit(&mut self, emitter: &mut AstEmitter) {
|
||||
let offset = emitter.emit.bytecode_offset();
|
||||
emitter.control_stack.register_break(offset);
|
||||
self.emit_jump(emitter);
|
||||
.emit(emitter, self.label);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ContinueEmitter {
|
||||
pub jump: JumpKind,
|
||||
pub label: Option<SourceAtomSetIndex>,
|
||||
}
|
||||
|
||||
impl Jump for ContinueEmitter {
|
||||
fn jump_kind(&mut self) -> &JumpKind {
|
||||
&self.jump
|
||||
}
|
||||
}
|
||||
|
||||
impl ContinueEmitter {
|
||||
pub fn emit(&mut self, emitter: &mut AstEmitter) {
|
||||
// TODO: For 'continue' statements in non local loops, we need to emit some extra bytecode.
|
||||
// see https://searchfox.org/mozilla-central/rev/a707541ff423ade0d81cef6488e6ecfa09273886/js/src/frontend/BytecodeEmitter.cpp#702-840
|
||||
let offset = emitter.emit.bytecode_offset();
|
||||
match self.label {
|
||||
Some(label) => emitter
|
||||
.control_stack
|
||||
.register_labelled_continue(label, offset),
|
||||
None => emitter.control_stack.register_continue(offset),
|
||||
NonLocalExitControl {
|
||||
registered_jump: RegisteredJump {
|
||||
kind: JumpKind::Goto,
|
||||
register_offset: |emitter, offset| match self.label {
|
||||
Some(label) => emitter
|
||||
.control_stack
|
||||
.register_labelled_continue(label, offset),
|
||||
None => emitter.control_stack.register_continue(offset),
|
||||
},
|
||||
},
|
||||
}
|
||||
self.emit_jump(emitter);
|
||||
.emit(emitter, self.label);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -429,6 +480,7 @@ where
|
|||
F1: Fn(&mut AstEmitter) -> Result<(), EmitError>,
|
||||
F2: Fn(&mut AstEmitter) -> Result<(), EmitError>,
|
||||
{
|
||||
pub enclosing_emitter_scope_depth: EmitterScopeDepth,
|
||||
pub test: F1,
|
||||
pub block: F2,
|
||||
}
|
||||
|
@ -438,12 +490,16 @@ where
|
|||
F2: Fn(&mut AstEmitter) -> Result<(), EmitError>,
|
||||
{
|
||||
pub fn emit(&mut self, emitter: &mut AstEmitter) -> Result<(), EmitError> {
|
||||
emitter.control_stack.open_loop(&mut emitter.emit);
|
||||
emitter
|
||||
.control_stack
|
||||
.open_loop(&mut emitter.emit, self.enclosing_emitter_scope_depth);
|
||||
|
||||
(self.test)(emitter)?;
|
||||
|
||||
InternalBreakEmitter {
|
||||
jump: JumpKind::IfEq,
|
||||
// add a registered jump for the conditional statement
|
||||
RegisteredJump {
|
||||
kind: JumpKind::IfEq,
|
||||
register_offset: |emitter, offset| emitter.control_stack.register_break(offset),
|
||||
}
|
||||
.emit(emitter);
|
||||
|
||||
|
@ -464,6 +520,7 @@ where
|
|||
F1: Fn(&mut AstEmitter) -> Result<(), EmitError>,
|
||||
F2: Fn(&mut AstEmitter) -> Result<(), EmitError>,
|
||||
{
|
||||
pub enclosing_emitter_scope_depth: EmitterScopeDepth,
|
||||
pub block: F2,
|
||||
pub test: F1,
|
||||
}
|
||||
|
@ -473,7 +530,9 @@ where
|
|||
F2: Fn(&mut AstEmitter) -> Result<(), EmitError>,
|
||||
{
|
||||
pub fn emit(&mut self, emitter: &mut AstEmitter) -> Result<(), EmitError> {
|
||||
emitter.control_stack.open_loop(&mut emitter.emit);
|
||||
emitter
|
||||
.control_stack
|
||||
.open_loop(&mut emitter.emit, self.enclosing_emitter_scope_depth);
|
||||
|
||||
(self.block)(emitter)?;
|
||||
|
||||
|
@ -483,8 +542,10 @@ where
|
|||
|
||||
(self.test)(emitter)?;
|
||||
|
||||
InternalBreakEmitter {
|
||||
jump: JumpKind::IfEq,
|
||||
// add a registered jump for the conditional statement
|
||||
RegisteredJump {
|
||||
kind: JumpKind::IfEq,
|
||||
register_offset: |emitter, offset| emitter.control_stack.register_break(offset),
|
||||
}
|
||||
.emit(emitter);
|
||||
|
||||
|
@ -501,6 +562,7 @@ where
|
|||
UpdateFn: Fn(&mut AstEmitter, &ExprT) -> Result<(), EmitError>,
|
||||
BlockFn: Fn(&mut AstEmitter) -> Result<(), EmitError>,
|
||||
{
|
||||
pub enclosing_emitter_scope_depth: EmitterScopeDepth,
|
||||
pub maybe_init: &'a Option<CondT>,
|
||||
pub maybe_test: &'a Option<ExprT>,
|
||||
pub maybe_update: &'a Option<ExprT>,
|
||||
|
@ -525,14 +587,18 @@ where
|
|||
}
|
||||
|
||||
// Emit loop head
|
||||
emitter.control_stack.open_loop(&mut emitter.emit);
|
||||
emitter
|
||||
.control_stack
|
||||
.open_loop(&mut emitter.emit, self.enclosing_emitter_scope_depth);
|
||||
|
||||
// if there is a test condition (ie x < 3) emit it
|
||||
if let Some(test) = self.maybe_test {
|
||||
(self.test)(emitter, &test)?;
|
||||
|
||||
InternalBreakEmitter {
|
||||
jump: JumpKind::IfEq,
|
||||
// add a registered jump for the conditional statement
|
||||
RegisteredJump {
|
||||
kind: JumpKind::IfEq,
|
||||
register_offset: |emitter, offset| emitter.control_stack.register_break(offset),
|
||||
}
|
||||
.emit(emitter);
|
||||
}
|
||||
|
@ -560,6 +626,7 @@ pub struct LabelEmitter<F1>
|
|||
where
|
||||
F1: Fn(&mut AstEmitter) -> Result<(), EmitError>,
|
||||
{
|
||||
pub enclosing_emitter_scope_depth: EmitterScopeDepth,
|
||||
pub name: SourceAtomSetIndex,
|
||||
pub body: F1,
|
||||
}
|
||||
|
@ -569,9 +636,11 @@ where
|
|||
F1: Fn(&mut AstEmitter) -> Result<(), EmitError>,
|
||||
{
|
||||
pub fn emit(&mut self, emitter: &mut AstEmitter) -> Result<(), EmitError> {
|
||||
emitter
|
||||
.control_stack
|
||||
.open_label(self.name, &mut emitter.emit);
|
||||
emitter.control_stack.open_label(
|
||||
self.name,
|
||||
&mut emitter.emit,
|
||||
self.enclosing_emitter_scope_depth,
|
||||
);
|
||||
|
||||
(self.body)(emitter)?;
|
||||
|
||||
|
@ -579,3 +648,57 @@ where
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NonLocalExitControl<F1>
|
||||
where
|
||||
F1: Fn(&mut AstEmitter, BytecodeOffset),
|
||||
{
|
||||
registered_jump: RegisteredJump<F1>,
|
||||
}
|
||||
|
||||
impl<F1> NonLocalExitControl<F1>
|
||||
where
|
||||
F1: Fn(&mut AstEmitter, BytecodeOffset),
|
||||
{
|
||||
pub fn emit(&mut self, emitter: &mut AstEmitter, label: Option<SourceAtomSetIndex>) {
|
||||
// Step 1: find the enclosing emitter scope
|
||||
let enclosing_emitter_scope_depth = match label {
|
||||
Some(label) => emitter
|
||||
.control_stack
|
||||
.find_labelled_control(label)
|
||||
.enclosing_emitter_scope_depth(),
|
||||
None => emitter
|
||||
.control_stack
|
||||
.innermost()
|
||||
.enclosing_emitter_scope_depth(),
|
||||
};
|
||||
|
||||
// Step 2: find the current emitter scope
|
||||
let current_scope_index = emitter.scope_stack.current_depth();
|
||||
|
||||
// Step 3: iterate over scopes that have been entered since the enclosing scope,
|
||||
// add a scope note hole for each one as we exit
|
||||
let mut holes = Vec::new();
|
||||
let scope_indicies = emitter
|
||||
.scope_stack
|
||||
.scope_note_indices_from_to(&enclosing_emitter_scope_depth, ¤t_scope_index);
|
||||
let mut parent_scope_note_index = emitter
|
||||
.scope_stack
|
||||
.get_scope_note_index_for(current_scope_index);
|
||||
for maybe_scope_note_index in scope_indicies.iter().rev() {
|
||||
let scope_note_index = emitter
|
||||
.emit
|
||||
.enter_scope_hole(maybe_scope_note_index, parent_scope_note_index);
|
||||
holes.push(scope_note_index);
|
||||
parent_scope_note_index = Some(scope_note_index);
|
||||
}
|
||||
|
||||
// Step 4: perform the jump
|
||||
self.registered_jump.emit(emitter);
|
||||
|
||||
// Step 5: close each scope hole after the jump
|
||||
for scope_note_hole_index in holes.iter() {
|
||||
emitter.emit.leave_scope_hole(*scope_note_hole_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,13 @@ use std::fmt::Write;
|
|||
pub fn dis(bc: &[u8]) -> String {
|
||||
let mut result = String::new();
|
||||
let mut iter = bc.iter();
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
let len = match iter.next() {
|
||||
Some(byte) => match Opcode::try_from(*byte) {
|
||||
Ok(op) => {
|
||||
write!(&mut result, "{:?}", op).unwrap();
|
||||
write!(&mut result, "{}", format!("{:05}: {:?}", offset, op)).unwrap();
|
||||
offset = offset + op.instruction_length();
|
||||
op.instruction_length()
|
||||
}
|
||||
Err(()) => {
|
||||
|
|
|
@ -11,13 +11,13 @@ use crate::gcthings::{GCThingIndex, GCThingList};
|
|||
use crate::opcode::Opcode;
|
||||
use crate::regexp::{RegExpItem, RegExpList};
|
||||
use crate::scope_notes::{ScopeNoteIndex, ScopeNoteList};
|
||||
use crate::script_atom_set::{ScriptAtomSet, ScriptAtomSetIndex};
|
||||
use crate::stencil::ScriptStencil;
|
||||
use ast::source_atom_set::SourceAtomSetIndex;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use scope::data::ScopeIndex;
|
||||
use scope::frame_slot::FrameSlot;
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::convert::TryInto;
|
||||
use std::fmt;
|
||||
|
@ -113,7 +113,9 @@ pub type u24 = u32;
|
|||
/// Low-level bytecode emitter.
|
||||
pub struct InstructionWriter {
|
||||
bytecode: Vec<u8>,
|
||||
atoms: ScriptAtomSet,
|
||||
|
||||
/// To de-duplicate atoms in gcthings list, note the index for each atom.
|
||||
atom_to_gcindex_map: HashMap<SourceAtomSetIndex, GCThingIndex>,
|
||||
|
||||
gcthings: GCThingList,
|
||||
scope_notes: ScopeNoteList,
|
||||
|
@ -173,8 +175,8 @@ impl InstructionWriter {
|
|||
pub fn new() -> Self {
|
||||
Self {
|
||||
bytecode: Vec::new(),
|
||||
atoms: ScriptAtomSet::new(),
|
||||
gcthings: GCThingList::new(),
|
||||
atom_to_gcindex_map: HashMap::new(),
|
||||
scope_notes: ScopeNoteList::new(),
|
||||
inner_functions: FunctionCreationDataList::new(),
|
||||
regexps: RegExpList::new(),
|
||||
|
@ -219,10 +221,6 @@ impl InstructionWriter {
|
|||
self.write_u32(usize::from(value) as u32);
|
||||
}
|
||||
|
||||
fn write_script_atom_set_index(&mut self, atom_index: ScriptAtomSetIndex) {
|
||||
self.write_u32(atom_index.into());
|
||||
}
|
||||
|
||||
fn write_offset(&mut self, offset: i32) {
|
||||
self.write_i32(offset);
|
||||
}
|
||||
|
@ -313,10 +311,6 @@ impl InstructionWriter {
|
|||
offset.offset + target_opcode.instruction_length()
|
||||
}
|
||||
|
||||
pub fn get_atom_index(&mut self, value: SourceAtomSetIndex) -> ScriptAtomSetIndex {
|
||||
self.atoms.insert(value)
|
||||
}
|
||||
|
||||
pub fn emit_jump_target_and_patch(&mut self, jumplist: &Vec<BytecodeOffset>) {
|
||||
let mut target = self.bytecode_offset();
|
||||
let last_jump = self.last_jump_target_offset;
|
||||
|
@ -467,9 +461,9 @@ impl InstructionWriter {
|
|||
self.write_u32(big_int_index);
|
||||
}
|
||||
|
||||
pub fn string(&mut self, atom_index: ScriptAtomSetIndex) {
|
||||
pub fn string(&mut self, atom_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::String);
|
||||
self.write_script_atom_set_index(atom_index);
|
||||
self.write_g_c_thing_index(atom_index);
|
||||
}
|
||||
|
||||
pub fn symbol(&mut self, symbol: u8) {
|
||||
|
@ -544,19 +538,19 @@ impl InstructionWriter {
|
|||
self.emit_op(Opcode::ObjWithProto);
|
||||
}
|
||||
|
||||
pub fn init_prop(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn init_prop(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::InitProp);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn init_hidden_prop(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn init_hidden_prop(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::InitHiddenProp);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn init_locked_prop(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn init_locked_prop(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::InitLockedProp);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn init_elem(&mut self) {
|
||||
|
@ -567,14 +561,14 @@ impl InstructionWriter {
|
|||
self.emit_op(Opcode::InitHiddenElem);
|
||||
}
|
||||
|
||||
pub fn init_prop_getter(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn init_prop_getter(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::InitPropGetter);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn init_hidden_prop_getter(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn init_hidden_prop_getter(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::InitHiddenPropGetter);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn init_elem_getter(&mut self) {
|
||||
|
@ -585,14 +579,14 @@ impl InstructionWriter {
|
|||
self.emit_op(Opcode::InitHiddenElemGetter);
|
||||
}
|
||||
|
||||
pub fn init_prop_setter(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn init_prop_setter(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::InitPropSetter);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn init_hidden_prop_setter(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn init_hidden_prop_setter(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::InitHiddenPropSetter);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn init_elem_setter(&mut self) {
|
||||
|
@ -603,14 +597,14 @@ impl InstructionWriter {
|
|||
self.emit_op(Opcode::InitHiddenElemSetter);
|
||||
}
|
||||
|
||||
pub fn get_prop(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn get_prop(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::GetProp);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn call_prop(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn call_prop(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::CallProp);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn get_elem(&mut self) {
|
||||
|
@ -621,19 +615,19 @@ impl InstructionWriter {
|
|||
self.emit_op(Opcode::CallElem);
|
||||
}
|
||||
|
||||
pub fn length(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn length(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::Length);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn set_prop(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn set_prop(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::SetProp);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn strict_set_prop(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn strict_set_prop(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::StrictSetProp);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn set_elem(&mut self) {
|
||||
|
@ -644,14 +638,14 @@ impl InstructionWriter {
|
|||
self.emit_op(Opcode::StrictSetElem);
|
||||
}
|
||||
|
||||
pub fn del_prop(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn del_prop(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::DelProp);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn strict_del_prop(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn strict_del_prop(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::StrictDelProp);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn del_elem(&mut self) {
|
||||
|
@ -670,23 +664,23 @@ impl InstructionWriter {
|
|||
self.emit_op(Opcode::SuperBase);
|
||||
}
|
||||
|
||||
pub fn get_prop_super(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn get_prop_super(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::GetPropSuper);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn get_elem_super(&mut self) {
|
||||
self.emit_op(Opcode::GetElemSuper);
|
||||
}
|
||||
|
||||
pub fn set_prop_super(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn set_prop_super(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::SetPropSuper);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn strict_set_prop_super(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn strict_set_prop_super(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::StrictSetPropSuper);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn set_elem_super(&mut self) {
|
||||
|
@ -859,14 +853,14 @@ impl InstructionWriter {
|
|||
self.emit_op(Opcode::StrictSpreadEval);
|
||||
}
|
||||
|
||||
pub fn implicit_this(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn implicit_this(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::ImplicitThis);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn g_implicit_this(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn g_implicit_this(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::GImplicitThis);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn call_site_obj(&mut self, object_index: GCThingIndex) {
|
||||
|
@ -1042,9 +1036,9 @@ impl InstructionWriter {
|
|||
self.write_u8(msg_number as u8);
|
||||
}
|
||||
|
||||
pub fn throw_set_const(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn throw_set_const(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::ThrowSetConst);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn try_(&mut self, jump_at_end_offset: i32) {
|
||||
|
@ -1087,9 +1081,9 @@ impl InstructionWriter {
|
|||
self.write_u24(localno);
|
||||
}
|
||||
|
||||
pub fn init_g_lexical(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn init_g_lexical(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::InitGLexical);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn init_aliased_lexical(&mut self, hops: u8, slot: u24) {
|
||||
|
@ -1113,24 +1107,24 @@ impl InstructionWriter {
|
|||
self.emit_op(Opcode::CheckThis);
|
||||
}
|
||||
|
||||
pub fn bind_g_name(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn bind_g_name(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::BindGName);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn bind_name(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn bind_name(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::BindName);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn get_name(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn get_name(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::GetName);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn get_g_name(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn get_g_name(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::GetGName);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn get_arg(&mut self, argno: u16) {
|
||||
|
@ -1149,19 +1143,19 @@ impl InstructionWriter {
|
|||
self.write_u24(slot);
|
||||
}
|
||||
|
||||
pub fn get_import(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn get_import(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::GetImport);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn get_bound_name(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn get_bound_name(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::GetBoundName);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn get_intrinsic(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn get_intrinsic(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::GetIntrinsic);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn callee(&mut self) {
|
||||
|
@ -1173,24 +1167,24 @@ impl InstructionWriter {
|
|||
self.write_u8(num_hops);
|
||||
}
|
||||
|
||||
pub fn set_name(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn set_name(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::SetName);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn strict_set_name(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn strict_set_name(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::StrictSetName);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn set_g_name(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn set_g_name(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::SetGName);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn strict_set_g_name(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn strict_set_g_name(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::StrictSetGName);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn set_arg(&mut self, argno: u16) {
|
||||
|
@ -1209,9 +1203,9 @@ impl InstructionWriter {
|
|||
self.write_u24(slot);
|
||||
}
|
||||
|
||||
pub fn set_intrinsic(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn set_intrinsic(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::SetIntrinsic);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn push_lexical_env(&mut self, lexical_scope_index: u32) {
|
||||
|
@ -1253,32 +1247,32 @@ impl InstructionWriter {
|
|||
self.emit_op(Opcode::BindVar);
|
||||
}
|
||||
|
||||
pub fn def_var(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn def_var(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::DefVar);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn def_fun(&mut self) {
|
||||
self.emit_op(Opcode::DefFun);
|
||||
}
|
||||
|
||||
pub fn def_let(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn def_let(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::DefLet);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn def_const(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn def_const(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::DefConst);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn check_global_or_eval_decl(&mut self) {
|
||||
self.emit_op(Opcode::CheckGlobalOrEvalDecl);
|
||||
}
|
||||
|
||||
pub fn del_name(&mut self, name_index: ScriptAtomSetIndex) {
|
||||
pub fn del_name(&mut self, name_index: GCThingIndex) {
|
||||
self.emit_op(Opcode::DelName);
|
||||
self.write_script_atom_set_index(name_index);
|
||||
self.write_g_c_thing_index(name_index);
|
||||
}
|
||||
|
||||
pub fn arguments(&mut self) {
|
||||
|
@ -1368,6 +1362,17 @@ impl InstructionWriter {
|
|||
|
||||
// @@@@ END METHODS @@@@
|
||||
|
||||
pub fn get_atom_gcthing_index(&mut self, atom: SourceAtomSetIndex) -> GCThingIndex {
|
||||
match self.atom_to_gcindex_map.get(&atom) {
|
||||
Some(index) => *index,
|
||||
None => {
|
||||
let index = self.gcthings.push_atom(atom);
|
||||
self.atom_to_gcindex_map.insert(atom, index);
|
||||
index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_function_gcthing_index(&mut self, fun_data: FunctionCreationData) -> GCThingIndex {
|
||||
let fun_data_index = self.inner_functions.push(fun_data);
|
||||
self.gcthings.push_function(fun_data_index)
|
||||
|
@ -1411,6 +1416,33 @@ impl InstructionWriter {
|
|||
self.scope_notes.leave_scope(index, offset);
|
||||
}
|
||||
|
||||
pub fn enter_scope_hole(
|
||||
&mut self,
|
||||
maybe_scope_note_index: &Option<ScopeNoteIndex>,
|
||||
parent_scope_note_index: Option<ScopeNoteIndex>,
|
||||
) -> ScopeNoteIndex {
|
||||
// TODO: the bytecode sequence before leaving scope (entering hole) depends on the kind
|
||||
// of scope (and also controls). This is currently only debug_leave_lexical_env because
|
||||
// there's only simple lexical scope.
|
||||
self.debug_leave_lexical_env();
|
||||
let offset = self.bytecode_offset();
|
||||
|
||||
let gcthing_index = match maybe_scope_note_index {
|
||||
Some(index) => self.scope_notes.get_scope_hole_gcthing_index(index),
|
||||
None => self
|
||||
.body_scope_index
|
||||
.expect("we should have a body scope index"),
|
||||
};
|
||||
|
||||
self.scope_notes
|
||||
.enter_scope(gcthing_index, offset, parent_scope_note_index)
|
||||
}
|
||||
|
||||
pub fn leave_scope_hole(&mut self, index: ScopeNoteIndex) {
|
||||
let offset = self.bytecode_offset();
|
||||
self.scope_notes.leave_scope(index, offset);
|
||||
}
|
||||
|
||||
pub fn switch_to_main(&mut self) {
|
||||
self.main_offset = self.bytecode_offset();
|
||||
}
|
||||
|
@ -1420,7 +1452,6 @@ impl From<InstructionWriter> for ScriptStencil {
|
|||
fn from(emit: InstructionWriter) -> Self {
|
||||
Self {
|
||||
bytecode: emit.bytecode,
|
||||
atoms: emit.atoms.into(),
|
||||
regexps: emit.regexps.into(),
|
||||
gcthings: emit.gcthings.into(),
|
||||
scope_notes: emit.scope_notes.into(),
|
||||
|
|
|
@ -22,6 +22,11 @@ pub enum NameLocation {
|
|||
FrameSlot(FrameSlot, BindingKind),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct EmitterScopeDepth {
|
||||
index: usize,
|
||||
}
|
||||
|
||||
// --- EmitterScope types
|
||||
//
|
||||
// These types are the variants of enum EmitterScope.
|
||||
|
@ -118,7 +123,7 @@ impl EmitterScope {
|
|||
}
|
||||
}
|
||||
|
||||
fn scope_note_index(&self) -> Option<ScopeNoteIndex> {
|
||||
pub fn scope_note_index(&self) -> Option<ScopeNoteIndex> {
|
||||
match self {
|
||||
EmitterScope::Global(scope) => scope.scope_note_index(),
|
||||
EmitterScope::Lexical(scope) => scope.scope_note_index(),
|
||||
|
@ -167,12 +172,16 @@ impl EmitterScopeStack {
|
|||
let scope_index = scope_data_map.get_global_index();
|
||||
let scope_data = scope_data_map.get_global_at(scope_index);
|
||||
|
||||
// The outermost scope should be the first item in the GC things list.
|
||||
// Enter global scope here, before emitting any name ops below.
|
||||
emit.enter_global_scope(scope_index);
|
||||
|
||||
if scope_data.bindings.len() > 0 {
|
||||
emit.check_global_or_eval_decl();
|
||||
}
|
||||
|
||||
for item in scope_data.iter() {
|
||||
let name_index = emit.get_atom_index(item.name());
|
||||
let name_index = emit.get_atom_gcthing_index(item.name());
|
||||
|
||||
match item.kind() {
|
||||
BindingKind::Var => {
|
||||
|
@ -193,8 +202,6 @@ impl EmitterScopeStack {
|
|||
|
||||
let scope = EmitterScope::Global(GlobalEmitterScope::new(scope_data));
|
||||
self.scope_stack.push(scope);
|
||||
|
||||
emit.enter_global_scope(scope_index);
|
||||
}
|
||||
|
||||
/// Leave the global scope. Call this once at the end of a top-level
|
||||
|
@ -285,4 +292,34 @@ impl EmitterScopeStack {
|
|||
|
||||
NameLocation::Dynamic
|
||||
}
|
||||
|
||||
pub fn current_depth(&mut self) -> EmitterScopeDepth {
|
||||
EmitterScopeDepth {
|
||||
index: self.scope_stack.len() - 1,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scope_note_indices_from_to(
|
||||
&self,
|
||||
from: &EmitterScopeDepth,
|
||||
to: &EmitterScopeDepth,
|
||||
) -> Vec<Option<ScopeNoteIndex>> {
|
||||
let mut indices = Vec::new();
|
||||
for scope in self
|
||||
.scope_stack
|
||||
.iter()
|
||||
.skip(from.index)
|
||||
.take(to.index - from.index)
|
||||
{
|
||||
indices.push(scope.scope_note_index());
|
||||
}
|
||||
indices
|
||||
}
|
||||
|
||||
pub fn get_scope_note_index_for(&self, index: EmitterScopeDepth) -> Option<ScopeNoteIndex> {
|
||||
self.scope_stack
|
||||
.get(index.index)
|
||||
.expect("scope should exist")
|
||||
.scope_note_index()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,18 +25,6 @@ pub enum FunctionKind {
|
|||
FunctionKindLimit = 8,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GeneratorKind {
|
||||
NotGenerator = 0,
|
||||
Generator = 1,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FunctionAsyncKind {
|
||||
SyncFunction = 0,
|
||||
AsyncFunction = 1,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
const FUNCTION_KIND_SHIFT: u16 = 0;
|
||||
#[allow(dead_code)]
|
||||
|
@ -122,7 +110,7 @@ const STABLE_ACROSS_CLONES: u16 = CONSTRUCTOR | LAMBDA | SELF_HOSTED | FUNCTION_
|
|||
// @@@@ END TYPES @@@@
|
||||
|
||||
impl FunctionFlags {
|
||||
pub fn new(flags: u16) -> Self {
|
||||
fn new(flags: u16) -> Self {
|
||||
debug_assert!(
|
||||
(((FunctionKind::FunctionKindLimit as u16) - 1) << FUNCTION_KIND_SHIFT)
|
||||
<= FUNCTION_KIND_MASK
|
||||
|
@ -130,6 +118,10 @@ impl FunctionFlags {
|
|||
|
||||
Self { flags }
|
||||
}
|
||||
|
||||
pub fn interpreted_normal() -> Self {
|
||||
Self::new(INTERPRETED_NORMAL)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -156,8 +148,6 @@ pub enum FunctionScript {
|
|||
pub struct FunctionCreationData {
|
||||
name: Option<SourceAtomSetIndex>,
|
||||
script: FunctionScript,
|
||||
generator_kind: GeneratorKind,
|
||||
async_kind: FunctionAsyncKind,
|
||||
flags: FunctionFlags,
|
||||
// FIXME: add more fields
|
||||
}
|
||||
|
@ -167,25 +157,16 @@ impl FunctionCreationData {
|
|||
pub fn non_lazy(
|
||||
name: Option<SourceAtomSetIndex>,
|
||||
script: ScriptStencilIndex,
|
||||
generator_kind: GeneratorKind,
|
||||
async_kind: FunctionAsyncKind,
|
||||
flags: FunctionFlags,
|
||||
) -> Self {
|
||||
Self {
|
||||
name,
|
||||
script: FunctionScript::NonLazy(NonLazyFunctionScript { script }),
|
||||
generator_kind,
|
||||
async_kind,
|
||||
flags,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lazy(
|
||||
name: Option<SourceAtomSetIndex>,
|
||||
generator_kind: GeneratorKind,
|
||||
async_kind: FunctionAsyncKind,
|
||||
flags: FunctionFlags,
|
||||
) -> Self {
|
||||
pub fn lazy(name: Option<SourceAtomSetIndex>, flags: FunctionFlags) -> Self {
|
||||
Self {
|
||||
name,
|
||||
script: FunctionScript::Lazy(LazyFunctionScript {
|
||||
|
@ -194,8 +175,6 @@ impl FunctionCreationData {
|
|||
force_strict: false,
|
||||
strict: false,
|
||||
}),
|
||||
generator_kind,
|
||||
async_kind,
|
||||
flags,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
use crate::ast_emitter::AstEmitter;
|
||||
use crate::emitter::EmitError;
|
||||
use crate::function::{FunctionCreationData, FunctionFlags};
|
||||
use crate::gcthings::GCThingIndex;
|
||||
use ast::source_atom_set::SourceAtomSetIndex;
|
||||
|
||||
/// Create a dummy function with empty script, to implement
|
||||
/// FunctionDeclarationEmitter without implementing FunctionScriptEmitter.
|
||||
pub struct DummyFunctionScriptEmitter {
|
||||
pub name: SourceAtomSetIndex,
|
||||
}
|
||||
|
||||
impl DummyFunctionScriptEmitter {
|
||||
pub fn emit(self, emitter: &mut AstEmitter) -> Result<GCThingIndex, EmitError> {
|
||||
let script_index = emitter.with_inner(|_emitter| {
|
||||
Err(EmitError::NotImplemented("TODO: FunctionDeclaration"))
|
||||
|
||||
// The following implementing is just a dummy to pass the
|
||||
// emitter part. The generated bytecode is completely wrong.
|
||||
//
|
||||
// Uncomment the following to check the behavior of
|
||||
// FunctionDeclarationEmitter in the enclosing script.
|
||||
/*
|
||||
let scope_data_map = &emitter.compilation_info.scope_data_map;
|
||||
emitter
|
||||
.scope_stack
|
||||
.enter_global(&mut emitter.emit, scope_data_map);
|
||||
|
||||
emitter.emit.undefined();
|
||||
emitter.emit.set_rval();
|
||||
emitter.emit.ret_rval();
|
||||
|
||||
emitter.scope_stack.leave_global(&mut emitter.emit);
|
||||
|
||||
Ok(())
|
||||
*/
|
||||
})?;
|
||||
|
||||
let fun_data = FunctionCreationData::non_lazy(
|
||||
Some(self.name),
|
||||
script_index,
|
||||
FunctionFlags::interpreted_normal(),
|
||||
);
|
||||
|
||||
Ok(emitter.emit.get_function_gcthing_index(fun_data))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FunctionDeclarationEmitter {
|
||||
pub fun: GCThingIndex,
|
||||
}
|
||||
|
||||
impl FunctionDeclarationEmitter {
|
||||
pub fn emit(self, emitter: &mut AstEmitter) {
|
||||
emitter.emit.lambda(self.fun);
|
||||
emitter.emit.def_fun();
|
||||
}
|
||||
}
|
|
@ -1,18 +1,20 @@
|
|||
use crate::function::FunctionCreationDataIndex;
|
||||
use crate::regexp::RegExpIndex;
|
||||
use ast::source_atom_set::SourceAtomSetIndex;
|
||||
use scope::data::ScopeIndex;
|
||||
|
||||
/// Corresponds to js::frontend::GCThingList::ListType
|
||||
/// in m-c/js/src/frontend/BytecodeSection.h.
|
||||
#[derive(Debug)]
|
||||
pub enum GCThing {
|
||||
Atom(SourceAtomSetIndex),
|
||||
Function(FunctionCreationDataIndex),
|
||||
RegExp(RegExpIndex),
|
||||
Scope(ScopeIndex),
|
||||
}
|
||||
|
||||
/// Index into GCThingList.things.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct GCThingIndex {
|
||||
index: usize,
|
||||
}
|
||||
|
@ -42,6 +44,12 @@ impl GCThingList {
|
|||
Self { things: Vec::new() }
|
||||
}
|
||||
|
||||
pub fn push_atom(&mut self, atom_index: SourceAtomSetIndex) -> GCThingIndex {
|
||||
let index = self.things.len();
|
||||
self.things.push(GCThing::Atom(atom_index));
|
||||
GCThingIndex::new(index)
|
||||
}
|
||||
|
||||
pub fn push_function(&mut self, fun_index: FunctionCreationDataIndex) -> GCThingIndex {
|
||||
let index = self.things.len();
|
||||
self.things.push(GCThing::Function(fun_index));
|
||||
|
|
|
@ -9,6 +9,7 @@ mod emitter;
|
|||
mod emitter_scope;
|
||||
mod expression_emitter;
|
||||
mod function;
|
||||
mod function_declaration_emitter;
|
||||
mod gcthings;
|
||||
mod object_emitter;
|
||||
pub mod opcode;
|
||||
|
@ -16,7 +17,6 @@ pub mod opcode_info;
|
|||
mod reference_op_emitter;
|
||||
mod regexp;
|
||||
mod scope_notes;
|
||||
mod script_atom_set;
|
||||
mod script_emitter;
|
||||
mod stencil;
|
||||
|
||||
|
@ -112,12 +112,12 @@ mod tests {
|
|||
bytecode("dis()"),
|
||||
vec![
|
||||
Opcode::GetGName as u8,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
Opcode::GImplicitThis as u8,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
|
|
@ -34,7 +34,7 @@ where
|
|||
// [stack] OBJ
|
||||
}
|
||||
None => {
|
||||
let name_index = emitter.emit.get_atom_index(self.key);
|
||||
let name_index = emitter.emit.get_atom_gcthing_index(self.key);
|
||||
|
||||
(self.value)(emitter)?;
|
||||
// [stack] OBJ VALUE
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
use crate::ast_emitter::AstEmitter;
|
||||
use crate::emitter::EmitError;
|
||||
use crate::emitter_scope::NameLocation;
|
||||
use crate::script_atom_set::ScriptAtomSetIndex;
|
||||
use crate::gcthings::GCThingIndex;
|
||||
use ast::source_atom_set::SourceAtomSetIndex;
|
||||
use scope::data::BindingKind;
|
||||
use scope::frame_slot::FrameSlot;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum AssignmentReferenceKind {
|
||||
GlobalVar(ScriptAtomSetIndex),
|
||||
GlobalLexical(ScriptAtomSetIndex),
|
||||
FrameSlot(FrameSlot),
|
||||
Dynamic(ScriptAtomSetIndex),
|
||||
GlobalVar(GCThingIndex),
|
||||
GlobalLexical(GCThingIndex),
|
||||
FrameSlotLexical(FrameSlot),
|
||||
FrameSlotNonLexical(FrameSlot),
|
||||
Dynamic(GCThingIndex),
|
||||
#[allow(dead_code)]
|
||||
Prop(ScriptAtomSetIndex),
|
||||
Prop(GCThingIndex),
|
||||
#[allow(dead_code)]
|
||||
Elem,
|
||||
}
|
||||
|
@ -34,7 +35,8 @@ impl AssignmentReference {
|
|||
match self.kind {
|
||||
AssignmentReferenceKind::GlobalVar(_) => 1,
|
||||
AssignmentReferenceKind::GlobalLexical(_) => 1,
|
||||
AssignmentReferenceKind::FrameSlot(_) => 0,
|
||||
AssignmentReferenceKind::FrameSlotLexical(_) => 0,
|
||||
AssignmentReferenceKind::FrameSlotNonLexical(_) => 0,
|
||||
AssignmentReferenceKind::Dynamic(_) => 1,
|
||||
AssignmentReferenceKind::Prop(_) => 1,
|
||||
AssignmentReferenceKind::Elem => 2,
|
||||
|
@ -44,8 +46,8 @@ impl AssignmentReference {
|
|||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum DeclarationReferenceKind {
|
||||
GlobalVar(ScriptAtomSetIndex),
|
||||
GlobalLexical(ScriptAtomSetIndex),
|
||||
GlobalVar(GCThingIndex),
|
||||
GlobalLexical(GCThingIndex),
|
||||
FrameSlot(FrameSlot),
|
||||
}
|
||||
|
||||
|
@ -68,6 +70,38 @@ enum CallKind {
|
|||
// FIXME: Support eval, Function#call, Function#apply etc.
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum ValueIsOnStack {
|
||||
No,
|
||||
Yes,
|
||||
}
|
||||
|
||||
fn check_temporary_dead_zone(
|
||||
emitter: &mut AstEmitter,
|
||||
slot: FrameSlot,
|
||||
is_on_stack: ValueIsOnStack,
|
||||
) {
|
||||
// FIXME: Use cache to avoid emitting check_lexical twice or more.
|
||||
// FIXME: Support aliased lexical.
|
||||
|
||||
// [stack] VAL?
|
||||
|
||||
if is_on_stack == ValueIsOnStack::No {
|
||||
emitter.emit.get_local(slot.into());
|
||||
// [stack] VAL
|
||||
}
|
||||
|
||||
emitter.emit.check_lexical(slot.into());
|
||||
// [stack] VAL
|
||||
|
||||
if is_on_stack == ValueIsOnStack::No {
|
||||
emitter.emit.pop();
|
||||
// [stack]
|
||||
}
|
||||
|
||||
// [stack] VAL?
|
||||
}
|
||||
|
||||
// See *ReferenceEmitter.
|
||||
// This uses struct to hide the details from the consumer.
|
||||
#[derive(Debug)]
|
||||
|
@ -87,7 +121,7 @@ pub struct GetNameEmitter {
|
|||
}
|
||||
impl GetNameEmitter {
|
||||
pub fn emit(self, emitter: &mut AstEmitter) {
|
||||
let name_index = emitter.emit.get_atom_index(self.name);
|
||||
let name_index = emitter.emit.get_atom_gcthing_index(self.name);
|
||||
let loc = emitter.lookup_name(self.name);
|
||||
|
||||
// [stack]
|
||||
|
@ -101,9 +135,14 @@ impl GetNameEmitter {
|
|||
emitter.emit.get_name(name_index);
|
||||
// [stack] VAL
|
||||
}
|
||||
NameLocation::FrameSlot(slot, _kind) => {
|
||||
NameLocation::FrameSlot(slot, kind) => {
|
||||
emitter.emit.get_local(slot.into());
|
||||
// [stack] VAL
|
||||
|
||||
if kind == BindingKind::Let || kind == BindingKind::Const {
|
||||
check_temporary_dead_zone(emitter, slot, ValueIsOnStack::Yes);
|
||||
// [stack] VAL
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +161,7 @@ where
|
|||
F: Fn(&mut AstEmitter) -> Result<(), EmitError>,
|
||||
{
|
||||
pub fn emit(self, emitter: &mut AstEmitter) -> Result<(), EmitError> {
|
||||
let key_index = emitter.emit.get_atom_index(self.key);
|
||||
let key_index = emitter.emit.get_atom_gcthing_index(self.key);
|
||||
|
||||
// [stack]
|
||||
|
||||
|
@ -151,7 +190,7 @@ where
|
|||
F: Fn(&mut AstEmitter) -> Result<(), EmitError>,
|
||||
{
|
||||
pub fn emit(self, emitter: &mut AstEmitter) -> Result<(), EmitError> {
|
||||
let key_index = emitter.emit.get_atom_index(self.key);
|
||||
let key_index = emitter.emit.get_atom_gcthing_index(self.key);
|
||||
|
||||
// [stack]
|
||||
|
||||
|
@ -253,7 +292,7 @@ pub struct NameReferenceEmitter {
|
|||
}
|
||||
impl NameReferenceEmitter {
|
||||
pub fn emit_for_call(self, emitter: &mut AstEmitter) -> CallReference {
|
||||
let name_index = emitter.emit.get_atom_index(self.name);
|
||||
let name_index = emitter.emit.get_atom_gcthing_index(self.name);
|
||||
let loc = emitter.lookup_name(self.name);
|
||||
|
||||
// [stack]
|
||||
|
@ -273,10 +312,15 @@ impl NameReferenceEmitter {
|
|||
emitter.emit.g_implicit_this(name_index);
|
||||
// [stack] CALLEE THIS
|
||||
}
|
||||
NameLocation::FrameSlot(slot, _kind) => {
|
||||
NameLocation::FrameSlot(slot, kind) => {
|
||||
emitter.emit.get_local(slot.into());
|
||||
// [stack] CALLEE
|
||||
|
||||
if kind == BindingKind::Let || kind == BindingKind::Const {
|
||||
check_temporary_dead_zone(emitter, slot, ValueIsOnStack::Yes);
|
||||
// [stack] CALLEE
|
||||
}
|
||||
|
||||
emitter.emit.undefined();
|
||||
// [stack] CALLEE THIS
|
||||
}
|
||||
|
@ -286,7 +330,7 @@ impl NameReferenceEmitter {
|
|||
}
|
||||
|
||||
pub fn emit_for_assignment(self, emitter: &mut AstEmitter) -> AssignmentReference {
|
||||
let name_index = emitter.emit.get_atom_index(self.name);
|
||||
let name_index = emitter.emit.get_atom_gcthing_index(self.name);
|
||||
let loc = emitter.lookup_name(self.name);
|
||||
|
||||
// [stack]
|
||||
|
@ -310,14 +354,18 @@ impl NameReferenceEmitter {
|
|||
|
||||
AssignmentReference::new(AssignmentReferenceKind::Dynamic(name_index))
|
||||
}
|
||||
NameLocation::FrameSlot(slot, _kind) => {
|
||||
AssignmentReference::new(AssignmentReferenceKind::FrameSlot(slot))
|
||||
NameLocation::FrameSlot(slot, kind) => {
|
||||
if kind == BindingKind::Let || kind == BindingKind::Const {
|
||||
AssignmentReference::new(AssignmentReferenceKind::FrameSlotLexical(slot))
|
||||
} else {
|
||||
AssignmentReference::new(AssignmentReferenceKind::FrameSlotNonLexical(slot))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emit_for_declaration(self, emitter: &mut AstEmitter) -> DeclarationReference {
|
||||
let name_index = emitter.emit.get_atom_index(self.name);
|
||||
let name_index = emitter.emit.get_atom_gcthing_index(self.name);
|
||||
let loc = emitter.lookup_name(self.name);
|
||||
|
||||
// [stack]
|
||||
|
@ -356,7 +404,7 @@ where
|
|||
F: Fn(&mut AstEmitter) -> Result<(), EmitError>,
|
||||
{
|
||||
pub fn emit_for_call(self, emitter: &mut AstEmitter) -> Result<CallReference, EmitError> {
|
||||
let key_index = emitter.emit.get_atom_index(self.key);
|
||||
let key_index = emitter.emit.get_atom_gcthing_index(self.key);
|
||||
|
||||
// [stack]
|
||||
|
||||
|
@ -383,7 +431,7 @@ where
|
|||
self,
|
||||
emitter: &mut AstEmitter,
|
||||
) -> Result<AssignmentReference, EmitError> {
|
||||
let key_index = emitter.emit.get_atom_index(self.key);
|
||||
let key_index = emitter.emit.get_atom_gcthing_index(self.key);
|
||||
|
||||
// [stack]
|
||||
|
||||
|
@ -585,7 +633,16 @@ where
|
|||
emitter.emit.set_name(name_index);
|
||||
// [stack] VAL
|
||||
}
|
||||
AssignmentReferenceKind::FrameSlot(slot) => {
|
||||
AssignmentReferenceKind::FrameSlotLexical(slot) => {
|
||||
// [stack] VAL
|
||||
|
||||
check_temporary_dead_zone(emitter, slot, ValueIsOnStack::No);
|
||||
// [stack] VAL
|
||||
|
||||
emitter.emit.set_local(slot.into());
|
||||
// [stack] VAL
|
||||
}
|
||||
AssignmentReferenceKind::FrameSlotNonLexical(slot) => {
|
||||
// [stack] VAL
|
||||
|
||||
emitter.emit.set_local(slot.into());
|
||||
|
|
|
@ -62,6 +62,13 @@ impl ScopeNoteList {
|
|||
ScopeNoteIndex::new(note_index)
|
||||
}
|
||||
|
||||
pub fn get_scope_hole_gcthing_index(&self, scope_note_index: &ScopeNoteIndex) -> GCThingIndex {
|
||||
self.notes
|
||||
.get(scope_note_index.index)
|
||||
.expect("Scope note should exist")
|
||||
.index
|
||||
}
|
||||
|
||||
pub fn leave_scope(&mut self, index: ScopeNoteIndex, offset: BytecodeOffset) {
|
||||
self.notes[usize::from(index)].end = offset;
|
||||
}
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
use ast::source_atom_set::SourceAtomSetIndex;
|
||||
use indexmap::set::IndexSet;
|
||||
|
||||
/// Index into ScriptAtomSet.atoms.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct ScriptAtomSetIndex {
|
||||
index: u32,
|
||||
}
|
||||
impl ScriptAtomSetIndex {
|
||||
fn new(index: u32) -> Self {
|
||||
Self { index }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ScriptAtomSetIndex> for u32 {
|
||||
fn from(index: ScriptAtomSetIndex) -> u32 {
|
||||
index.index
|
||||
}
|
||||
}
|
||||
|
||||
/// List of atoms referred from bytecode.
|
||||
///
|
||||
/// Maps to JSScript::atoms() in js/src/vm/JSScript.h.
|
||||
pub struct ScriptAtomSet {
|
||||
// This keeps the insertion order.
|
||||
atoms: IndexSet<SourceAtomSetIndex>,
|
||||
}
|
||||
|
||||
impl ScriptAtomSet {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
atoms: IndexSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, value: SourceAtomSetIndex) -> ScriptAtomSetIndex {
|
||||
let (index, _) = self.atoms.insert_full(value);
|
||||
ScriptAtomSetIndex::new(index as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ScriptAtomSet> for Vec<SourceAtomSetIndex> {
|
||||
fn from(set: ScriptAtomSet) -> Vec<SourceAtomSetIndex> {
|
||||
set.atoms.into_iter().collect()
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ use crate::gcthings::GCThing;
|
|||
use crate::regexp::RegExpItem;
|
||||
use crate::scope_notes::ScopeNote;
|
||||
|
||||
use ast::source_atom_set::SourceAtomSetIndex;
|
||||
use scope::data::ScopeData;
|
||||
use scope::frame_slot::FrameSlot;
|
||||
|
||||
|
@ -38,7 +37,6 @@ impl<'alloc> EmitResult<'alloc> {
|
|||
#[derive(Debug)]
|
||||
pub struct ScriptStencil {
|
||||
pub bytecode: Vec<u8>,
|
||||
pub atoms: Vec<SourceAtomSetIndex>,
|
||||
pub regexps: Vec<RegExpItem>,
|
||||
pub gcthings: Vec<GCThing>,
|
||||
pub scope_notes: Vec<ScopeNote>,
|
||||
|
@ -87,7 +85,9 @@ impl From<ScriptStencilIndex> for usize {
|
|||
/// List of stencil scripts.
|
||||
#[derive(Debug)]
|
||||
pub struct ScriptStencilList {
|
||||
scripts: Vec<ScriptStencil>,
|
||||
/// Uses Option to allow `allocate()` and `populate()` to be called
|
||||
/// separately.
|
||||
scripts: Vec<Option<ScriptStencil>>,
|
||||
}
|
||||
|
||||
impl ScriptStencilList {
|
||||
|
@ -99,13 +99,26 @@ impl ScriptStencilList {
|
|||
|
||||
pub fn push(&mut self, script: ScriptStencil) -> ScriptStencilIndex {
|
||||
let index = self.scripts.len();
|
||||
self.scripts.push(script);
|
||||
self.scripts.push(Some(script));
|
||||
ScriptStencilIndex::new(index)
|
||||
}
|
||||
|
||||
pub fn allocate(&mut self) -> ScriptStencilIndex {
|
||||
let index = self.scripts.len();
|
||||
self.scripts.push(None);
|
||||
ScriptStencilIndex::new(index)
|
||||
}
|
||||
|
||||
pub fn populate(&mut self, index: ScriptStencilIndex, script: ScriptStencil) {
|
||||
self.scripts[usize::from(index)].replace(script);
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ScriptStencilList> for Vec<ScriptStencil> {
|
||||
fn from(list: ScriptStencilList) -> Vec<ScriptStencil> {
|
||||
list.scripts
|
||||
.into_iter()
|
||||
.map(|g| g.expect("Should be populated"))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"8e424d01abd384e3d5f13bf921c8f4bc58306b3f41825dc821e60c5220efb7e0","src/ast_builder.rs":"1c7f5bd154d626ca560091764bf13c480e84295a2003ecd5d3157f242d03cfe3","src/context_stack.rs":"29331d03cd4c8ee9283cb426ebe893b7ba6ad6d8a69016399c4d92a81cb1363b","src/declaration_kind.rs":"fdfda2fe408cce1c637d17fee0813160619450472c6de9befc36ebeed892cc3c","src/early_error_checker.rs":"04b5e8dfc2db295c073cd97abd0e8a96ce641ab46ba9a06338f5154ff72377b0","src/early_errors.rs":"8674454af7ac5efe51eb6a8e2abe088aad5560e0a0bd88a3eae66c90f1527149","src/error.rs":"507e4dd9c66720f3da2db135c3024392d8aaac5ccdb90c7f7463ccb2eff7efa8","src/lib.rs":"a40b11e1dda1afcccef5fc86a2030c326d38feb31e24596e602930dcad28f1ec","src/parser_tables_generated.rs":"8a15ec6a66b92884f00a6d6616dd537d36e5135c6ba6f72f1b3def692bd6103d","src/stack_value_generated.rs":"d8696a671368e2565d589922e3a46d20667ed3e17e29953e69b970470e9639ee","src/token.rs":"479f4cb97d2e6bc654a70634f3809817cc73eaf749c845643beb3556b9ead383","src/traits/mod.rs":"bcc2fa63444ba4c763dc996f410a6871f2cdc3bde54e1924ca8cc25cba92674a"},"package":null}
|
||||
{"files":{"Cargo.toml":"8e424d01abd384e3d5f13bf921c8f4bc58306b3f41825dc821e60c5220efb7e0","src/ast_builder.rs":"8b10743ebbc3390d1158cb44ff5c87fbb653d62521f3e1274565d0061eebe095","src/context_stack.rs":"29331d03cd4c8ee9283cb426ebe893b7ba6ad6d8a69016399c4d92a81cb1363b","src/declaration_kind.rs":"fdfda2fe408cce1c637d17fee0813160619450472c6de9befc36ebeed892cc3c","src/early_error_checker.rs":"150a106a8f0901b72ae40581f0c12f785983514cbc9042404ed6cf4315693d60","src/early_errors.rs":"8674454af7ac5efe51eb6a8e2abe088aad5560e0a0bd88a3eae66c90f1527149","src/error.rs":"507e4dd9c66720f3da2db135c3024392d8aaac5ccdb90c7f7463ccb2eff7efa8","src/lib.rs":"a40b11e1dda1afcccef5fc86a2030c326d38feb31e24596e602930dcad28f1ec","src/parser_tables_generated.rs":"a99bc928a0ac9ffc44564e5c086fee1b195c6be5e05cfc4bf92946fdc963631e","src/stack_value_generated.rs":"d8696a671368e2565d589922e3a46d20667ed3e17e29953e69b970470e9639ee","src/token.rs":"479f4cb97d2e6bc654a70634f3809817cc73eaf749c845643beb3556b9ead383","src/traits/mod.rs":"bcc2fa63444ba4c763dc996f410a6871f2cdc3bde54e1924ca8cc25cba92674a"},"package":null}
|
|
@ -2223,6 +2223,25 @@ impl<'alloc> AstBuilder<'alloc> {
|
|||
CompoundAssignmentOperator::And { loc: token.loc }
|
||||
}
|
||||
|
||||
pub fn logical_or_assign_op(
|
||||
&self,
|
||||
token: arena::Box<'alloc, Token>,
|
||||
) -> CompoundAssignmentOperator {
|
||||
CompoundAssignmentOperator::LogicalOr { loc: token.loc }
|
||||
}
|
||||
pub fn logical_and_assign_op(
|
||||
&self,
|
||||
token: arena::Box<'alloc, Token>,
|
||||
) -> CompoundAssignmentOperator {
|
||||
CompoundAssignmentOperator::LogicalAnd { loc: token.loc }
|
||||
}
|
||||
pub fn coalesce_assign_op(
|
||||
&self,
|
||||
token: arena::Box<'alloc, Token>,
|
||||
) -> CompoundAssignmentOperator {
|
||||
CompoundAssignmentOperator::Coalesce { loc: token.loc }
|
||||
}
|
||||
|
||||
pub fn box_assign_op(
|
||||
&self,
|
||||
op: CompoundAssignmentOperator,
|
||||
|
@ -2231,6 +2250,7 @@ impl<'alloc> AstBuilder<'alloc> {
|
|||
}
|
||||
|
||||
// AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression
|
||||
// AssignmentExpression : LeftHandSideExpression LogicalAssignmentOperator AssignmentExpression
|
||||
pub fn compound_assignment_expr(
|
||||
&self,
|
||||
left_hand_side: arena::Box<'alloc, Expression<'alloc>>,
|
||||
|
|
|
@ -565,8 +565,12 @@ pub trait EarlyErrorChecker<'alloc> {
|
|||
CatchParameterEarlyErrorsContext::new_with_binding_pattern()
|
||||
};
|
||||
|
||||
let param_index = self.context_metadata_mut().find_first_binding(start_of_bindings_offset);
|
||||
let body_index = self.context_metadata_mut().find_first_binding(end_of_bindings_offset);
|
||||
let param_index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_binding(start_of_bindings_offset);
|
||||
let body_index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_binding(end_of_bindings_offset);
|
||||
declare_param(
|
||||
self.context_metadata(),
|
||||
self.atoms(),
|
||||
|
@ -589,8 +593,13 @@ pub trait EarlyErrorChecker<'alloc> {
|
|||
}
|
||||
|
||||
// Check bindings in Catch with no parameter and Block.
|
||||
fn check_catch_no_param_bindings(&mut self, start_of_catch_offset: usize) -> Result<'alloc, ()> {
|
||||
let body_index = self.context_metadata_mut().find_first_binding(start_of_catch_offset);
|
||||
fn check_catch_no_param_bindings(
|
||||
&mut self,
|
||||
start_of_catch_offset: usize,
|
||||
) -> Result<'alloc, ()> {
|
||||
let body_index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_binding(start_of_catch_offset);
|
||||
|
||||
let param_context = CatchParameterEarlyErrorsContext::new_with_binding_identifier();
|
||||
let mut block_context = CatchBlockEarlyErrorsContext::new(param_context);
|
||||
|
@ -614,8 +623,12 @@ pub trait EarlyErrorChecker<'alloc> {
|
|||
) -> Result<'alloc, ()> {
|
||||
let mut head_context = LexicalForHeadEarlyErrorsContext::new();
|
||||
|
||||
let head_index = self.context_metadata_mut().find_first_binding(start_of_bindings_offset);
|
||||
let body_index = self.context_metadata_mut().find_first_binding(end_of_bindings_offset);
|
||||
let head_index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_binding(start_of_bindings_offset);
|
||||
let body_index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_binding(end_of_bindings_offset);
|
||||
declare_lexical_for_head(
|
||||
self.context_metadata(),
|
||||
self.atoms(),
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"8bb197a613ba0328d4295fdbd824e54f2dc1ae7cf688abb9f0650d39733ef4f2","benches/__finStreamer-proto.js":"44edc00a99a8904f8c6bb0c42c7ba4f96ad611e61191d2702ecb228ae6d7b35d","benches/parser.rs":"6cb13b135513e86b94e1bbe1470156f182355078c2e34bf8d9deba1c67daf4b9","benches/simple.js":"fbb50c1c49c0b1e3740a79407a834248c1f8ebdb1b72530c0fc6df57d079f252","src/lexer.rs":"9648e0d88f490f446965ddb444220f270f571199cfff5e63a0ccf3dc07be63c6","src/lib.rs":"87a6a2bb77088574422ecd6598bcdb2838a676d34ce557fe1503abdce941fcf2","src/numeric_value.rs":"f429c50640eb35a53aa5ffdf71de305da30747e568dc10219c54b766372f6eca","src/parser.rs":"6735dd5b4241287a06dedf52f867d35da782e618542f35b1c0a5f579117878f5","src/queue_stack.rs":"d1826d4ef0b0cf3c4e6d5d83a3b5cb1b9ea3e2eda25d8bb0d13fce50d6062d37","src/simulator.rs":"4018f71a08900df11f407a3ccee1f6ca68059a0e922260a1bc2dd808b78dbc2f","src/tests.rs":"a48030a0b0e5c5a9c75916bb63de3d3524e66733dbb86c1526ec55bdf25787a4"},"package":null}
|
||||
{"files":{"Cargo.toml":"8bb197a613ba0328d4295fdbd824e54f2dc1ae7cf688abb9f0650d39733ef4f2","benches/__finStreamer-proto.js":"44edc00a99a8904f8c6bb0c42c7ba4f96ad611e61191d2702ecb228ae6d7b35d","benches/parser.rs":"6cb13b135513e86b94e1bbe1470156f182355078c2e34bf8d9deba1c67daf4b9","benches/simple.js":"fbb50c1c49c0b1e3740a79407a834248c1f8ebdb1b72530c0fc6df57d079f252","src/lexer.rs":"a2c942415a6dba5a768da71ddfec32eb194b482679b0a0edf10c949b8d386c63","src/lib.rs":"ef17c34e95e05724e8772280172042b065c57883d7a043cb427840456982f9bd","src/numeric_value.rs":"f429c50640eb35a53aa5ffdf71de305da30747e568dc10219c54b766372f6eca","src/parser.rs":"c8c7903248a565f79bf642641d4c95d5d4838ba1ae38294f583721ce6ba2bafd","src/queue_stack.rs":"d1826d4ef0b0cf3c4e6d5d83a3b5cb1b9ea3e2eda25d8bb0d13fce50d6062d37","src/simulator.rs":"829102c7f5cec8ab79179115630175cfa7c865269e8ef99e7896cbbad3678e96","src/tests.rs":"ea5df36f73d74692a6f26f4148d3d0b541a9e4baae16479100d54d2898602c3f"},"package":null}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -81,7 +81,7 @@ fn parse<'alloc>(
|
|||
if t.terminal_id == TerminalId::End {
|
||||
break;
|
||||
}
|
||||
parser.write_token(&t)?;
|
||||
parser.write_token(t)?;
|
||||
}
|
||||
parser.close(tokens.offset())
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ pub fn is_partial_script<'alloc>(
|
|||
if t.terminal_id == TerminalId::End {
|
||||
break;
|
||||
}
|
||||
parser.write_token(&t)?;
|
||||
parser.write_token(t)?;
|
||||
}
|
||||
Ok(!parser.can_close())
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::queue_stack::QueueStack;
|
||||
use crate::simulator::Simulator;
|
||||
use ast::arena;
|
||||
use ast::SourceLocation;
|
||||
use generated_parser::{
|
||||
full_actions, AstBuilder, AstBuilderDelegate, ErrorCode, ParseError, ParserTrait, Result,
|
||||
|
@ -118,7 +119,7 @@ impl<'alloc> Parser<'alloc> {
|
|||
*self.state_stack.last().unwrap()
|
||||
}
|
||||
|
||||
pub fn write_token(&mut self, token: &Token) -> Result<'alloc, ()> {
|
||||
pub fn write_token(&mut self, token: arena::Box<'alloc, Token>) -> Result<'alloc, ()> {
|
||||
json_trace!({
|
||||
"method": "write_token",
|
||||
"is_on_new_line": token.is_on_new_line,
|
||||
|
@ -126,9 +127,10 @@ impl<'alloc> Parser<'alloc> {
|
|||
"end": token.loc.end,
|
||||
});
|
||||
// Shift the token with the associated StackValue.
|
||||
let term = Term::Terminal(token.terminal_id);
|
||||
let accept = self.shift(TermValue {
|
||||
term: Term::Terminal(token.terminal_id),
|
||||
value: StackValue::Token(self.handler.alloc(token.clone())),
|
||||
term,
|
||||
value: StackValue::Token(token),
|
||||
})?;
|
||||
// JavaScript grammar accepts empty inputs, therefore we can never
|
||||
// accept any program before receiving a TerminalId::End.
|
||||
|
@ -146,7 +148,7 @@ impl<'alloc> Parser<'alloc> {
|
|||
let token = Token::basic_token(TerminalId::End, loc);
|
||||
let accept = self.shift(TermValue {
|
||||
term: Term::Terminal(TerminalId::End),
|
||||
value: StackValue::Token(self.handler.alloc(token.clone())),
|
||||
value: StackValue::Token(self.handler.alloc(token)),
|
||||
})?;
|
||||
// Adding a TerminalId::End would either lead to a parse error, or to
|
||||
// accepting the current input. In which case we return matching node
|
||||
|
@ -232,11 +234,7 @@ impl<'alloc> Parser<'alloc> {
|
|||
}
|
||||
|
||||
pub fn can_accept_terminal(&self, t: TerminalId) -> bool {
|
||||
let bogus_loc = SourceLocation::new(0, 0);
|
||||
let result = self
|
||||
.simulator()
|
||||
.write_token(&Token::basic_token(t, bogus_loc))
|
||||
.is_ok();
|
||||
let result = self.simulator().write_token(t).is_ok();
|
||||
json_trace!({
|
||||
"can_accept": result,
|
||||
"terminal": format!("{:?}", t),
|
||||
|
|
|
@ -126,10 +126,10 @@ impl<'alloc, 'parser> Simulator<'alloc, 'parser> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn write_token(&mut self, token: &Token) -> Result<'alloc, ()> {
|
||||
pub fn write_token(&mut self, t: TerminalId) -> Result<'alloc, ()> {
|
||||
// Shift the token with the associated StackValue.
|
||||
let accept = self.shift(TermValue {
|
||||
term: Term::Terminal(token.terminal_id),
|
||||
term: Term::Terminal(t),
|
||||
value: (),
|
||||
})?;
|
||||
// JavaScript grammar accepts empty inputs, therefore we can never
|
||||
|
|
|
@ -181,8 +181,8 @@ fn assert_same_tokens<'alloc>(left: &str, right: &str) {
|
|||
if left_token.terminal_id == TerminalId::End {
|
||||
break;
|
||||
}
|
||||
left_parser.write_token(&left_token).unwrap();
|
||||
right_parser.write_token(&right_token).unwrap();
|
||||
left_parser.write_token(left_token).unwrap();
|
||||
right_parser.write_token(right_token).unwrap();
|
||||
}
|
||||
left_parser.close(left_lexer.offset()).unwrap();
|
||||
right_parser.close(left_lexer.offset()).unwrap();
|
||||
|
@ -203,7 +203,7 @@ fn assert_can_close_after<'alloc, T: IntoChunks<'alloc>>(code: T) {
|
|||
if t.terminal_id == TerminalId::End {
|
||||
break;
|
||||
}
|
||||
parser.write_token(&t).unwrap();
|
||||
parser.write_token(t).unwrap();
|
||||
}
|
||||
assert!(parser.can_close());
|
||||
}
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -527,6 +527,8 @@ AssignmentExpression[In, Yield, Await] :
|
|||
=> assignment_expr($0, $2)
|
||||
LeftHandSideExpression[?Yield, ?Await] AssignmentOperator AssignmentExpression[?In, ?Yield, ?Await]
|
||||
=> compound_assignment_expr($0, $1, $2)
|
||||
LeftHandSideExpression[?Yield, ?Await] LogicalAssignmentOperator AssignmentExpression[?In, ?Yield, ?Await]
|
||||
=> compound_assignment_expr($0, $1, $2)
|
||||
|
||||
@returns CompoundAssignmentOperator
|
||||
AssignmentOperator :
|
||||
|
@ -555,6 +557,14 @@ AssignmentOperator :
|
|||
`**=`
|
||||
=> box_assign_op(pow_assign_op($0))
|
||||
|
||||
@returns CompoundAssignmentOperator
|
||||
LogicalAssignmentOperator :
|
||||
`&&=`
|
||||
=> box_assign_op(logical_and_assign_op($0))
|
||||
`||=`
|
||||
=> box_assign_op(logical_or_assign_op($0))
|
||||
`??=`
|
||||
=> box_assign_op(coalesce_assign_op($0))
|
||||
|
||||
AssignmentPattern[Yield, Await] :
|
||||
ObjectAssignmentPattern[?Yield, ?Await]
|
||||
|
|
|
@ -26,6 +26,7 @@ import jsparagus.lexer
|
|||
|
||||
def _get_punctuators():
|
||||
punctuators = '''
|
||||
&&= ||= ??=
|
||||
{ ( ) [ ] . ... ; , < > <= >= == != === !== + - * % ** ++ --
|
||||
<< >> >>> & | ^ ! ~ && || ? : = += -= *= %=
|
||||
**= ><<= >>= >>>= &= |= ^= =>
|
||||
|
|
|
@ -17,6 +17,9 @@ from .. import types
|
|||
|
||||
|
||||
TERMINAL_NAMES = {
|
||||
'&&=': 'LogicalAndAssign',
|
||||
'||=': 'LogicalOrAssign',
|
||||
'??=': 'CoalesceAssign',
|
||||
'{': 'OpenBrace',
|
||||
'}': 'CloseBrace',
|
||||
'(': 'OpenParenthesis',
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,101 +0,0 @@
|
|||
language: rust
|
||||
# sudo is required to enable kcov to use the personality syscall
|
||||
sudo: required
|
||||
dist: trusty
|
||||
cache: cargo
|
||||
|
||||
rust:
|
||||
- nightly
|
||||
- beta
|
||||
- stable
|
||||
- 1.31.0
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- FEATURES='--features "regexp regexp_macros"'
|
||||
|
||||
before_script:
|
||||
- eval git pull --rebase https://github.com/Geal/nom master
|
||||
- eval git log --pretty=oneline HEAD~5..HEAD
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- rust: nightly
|
||||
env: FEATURES='--no-default-features'
|
||||
- rust: nightly
|
||||
env: FEATURES='--no-default-features --features "alloc"'
|
||||
- rust: stable
|
||||
env: FEATURES=''
|
||||
- rust: nightly
|
||||
env: DOC_FEATURES='--features "std lexical regexp regexp_macros" --no-default-features'
|
||||
before_script:
|
||||
- export PATH=$HOME/.cargo/bin:$PATH
|
||||
script:
|
||||
- eval cargo doc --verbose $DOC_FEATURES
|
||||
- rust: nightly
|
||||
env: FEATURES=''
|
||||
before_script:
|
||||
- export PATH=$HOME/.cargo/bin:$PATH
|
||||
- cargo install cargo-update || echo "cargo-update already installed"
|
||||
- cargo install cargo-travis || echo "cargo-travis already installed"
|
||||
- cargo install-update -a
|
||||
- mkdir -p target/kcov-master
|
||||
script:
|
||||
cargo coveralls --verbose --all-features
|
||||
allow_failures:
|
||||
- rust: stable
|
||||
env: FEATURES=''
|
||||
before_script:
|
||||
- export PATH=$HOME/.cargo/bin:$PATH
|
||||
- rustup component add rustfmt-preview
|
||||
script:
|
||||
- eval cargo fmt -- --write-mode=diff
|
||||
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/9c035a194ac4fd4cc061
|
||||
on_success: change
|
||||
on_failure: always
|
||||
on_start: false
|
||||
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libcurl4-openssl-dev
|
||||
- libelf-dev
|
||||
- libdw-dev
|
||||
- binutils-dev
|
||||
- cmake
|
||||
sources:
|
||||
- kalakris-cmake
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- /home/travis/.cargo
|
||||
|
||||
before_cache:
|
||||
- rm -rf /home/travis/.cargo/registry
|
||||
|
||||
script:
|
||||
- eval cargo build --verbose $FEATURES
|
||||
- eval cargo test --verbose $FEATURES
|
||||
|
||||
after_success: |
|
||||
case "$TRAVIS_RUST_VERSION" in
|
||||
nightly)
|
||||
if [ "${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH}" != "master" ]; then
|
||||
git fetch &&
|
||||
git checkout master &&
|
||||
cargo bench --verbose
|
||||
fi
|
||||
|
||||
if [ "$FEATURES" == '--features "regexp regexp_macros"' ]; then
|
||||
cargo bench --verbose
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
;;
|
||||
esac
|
Загрузка…
Ссылка в новой задаче