Skip to content

Commit

Permalink
Catchup new_lexer (#657)
Browse files Browse the repository at this point in the history
* Added CLEAN_JS and MINI_JS benches (#581)

* Added CLEAN_JS and MINI_JS benches

These benches are arbitrary code which is subject to change,
functionally the programs are identical.

* Forgot semicolon

* Adding parsing benchmarks for CleanJS & MiniJS

Added identical benchmark cases for parser.

* Migrating Clean and Mini benchmarks to new format

Adding js scripts in bench_scripts & moving exec, full and parser
benchmarks to new include_str!() macro.

* Move `require_object_coercible` to `Value` (#654)

Co-authored-by: neeldug <5161147+neeldug@users.noreply.github.com>
Co-authored-by: HalidOdat <halidodat@gmail.com>
  • Loading branch information
3 people authored Aug 22, 2020
1 parent 1b7697f commit 7f23537
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 27 deletions.
15 changes: 15 additions & 0 deletions boa/benches/bench_scripts/clean_js.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
!function () {
var M = new Array();
for (i = 0; i < 100; i++) {
M.push(Math.floor(Math.random() * 100));
}
var test = [];
for (i = 0; i < 100; i++) {
if (M[i] > 50) {
test.push(M[i]);
}
}
test.forEach(elem => {
0
});
}();
1 change: 1 addition & 0 deletions boa/benches/bench_scripts/mini_js.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!function(){var r=new Array();for(i=0;i<100;i++)r.push(Math.floor(100*Math.random()));var a=[];for(i=0;i<100;i++)r[i]>50&&a.push(r[i]);a.forEach(i=>{0})}();
28 changes: 28 additions & 0 deletions boa/benches/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,32 @@ fn arithmetic_operations(c: &mut Criterion) {
});
}

static CLEAN_JS: &str = include_str!("bench_scripts/clean_js.js");

fn clean_js(c: &mut Criterion) {
let realm = Realm::create();
let mut engine = Interpreter::new(realm);
let mut lexer = Lexer::new(CLEAN_JS);
lexer.lex().expect("failed to lex");
let nodes = Parser::new(&lexer.tokens).parse_all().unwrap();
c.bench_function("Clean js (Execution)", move |b| {
b.iter(|| black_box(&nodes).run(&mut engine).unwrap())
});
}

static MINI_JS: &str = include_str!("bench_scripts/mini_js.js");

fn mini_js(c: &mut Criterion) {
let realm = Realm::create();
let mut engine = Interpreter::new(realm);
let mut lexer = Lexer::new(MINI_JS);
lexer.lex().expect("failed to lex");
let nodes = Parser::new(&lexer.tokens).parse_all().unwrap();
c.bench_function("Mini js (Execution)", move |b| {
b.iter(|| black_box(&nodes).run(&mut engine).unwrap())
});
}

criterion_group!(
execution,
create_realm,
Expand All @@ -341,5 +367,7 @@ criterion_group!(
boolean_object_access,
string_object_access,
arithmetic_operations,
clean_js,
mini_js,
);
criterion_main!(execution);
18 changes: 18 additions & 0 deletions boa/benches/full.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,22 @@ fn arithmetic_operations(c: &mut Criterion) {
});
}

static CLEAN_JS: &str = include_str!("bench_scripts/clean_js.js");

fn clean_js(c: &mut Criterion) {
c.bench_function("Clean js (Full)", move |b| {
b.iter(|| exec(black_box(CLEAN_JS)))
});
}

static MINI_JS: &str = include_str!("bench_scripts/mini_js.js");

fn mini_js(c: &mut Criterion) {
c.bench_function("Mini js (Full)", move |b| {
b.iter(|| exec(black_box(MINI_JS)))
});
}

criterion_group!(
full,
symbol_creation,
Expand All @@ -200,5 +216,7 @@ criterion_group!(
boolean_object_access,
string_object_access,
arithmetic_operations,
clean_js,
mini_js,
);
criterion_main!(full);
28 changes: 28 additions & 0 deletions boa/benches/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,40 @@ fn goal_symbol_switch(c: &mut Criterion) {
});
}

static CLEAN_JS: &str = include_str!("bench_scripts/clean_js.js");

fn clean_js(c: &mut Criterion) {
c.bench_function("Clean js (Parser)", move |b| {
b.iter(|| {
let mut lexer = Lexer::new(black_box(CLEAN_JS));
lexer.lex().expect("failed to lex");

Parser::new(&black_box(lexer.tokens)).parse_all()
})
});
}

static MINI_JS: &str = include_str!("bench_scripts/mini_js.js");

fn mini_js(c: &mut Criterion) {
c.bench_function("Mini js (Parser)", move |b| {
b.iter(|| {
let mut lexer = Lexer::new(black_box(MINI_JS));
lexer.lex().expect("failed to lex");

Parser::new(&black_box(lexer.tokens)).parse_all()
})
});
}

criterion_group!(
parser,
expression_parser,
hello_world_parser,
for_loop_parser,
long_file_parser,
goal_symbol_switch,
clean_js,
mini_js,
);
criterion_main!(parser);
14 changes: 7 additions & 7 deletions boa/src/builtins/string/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.concat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/concat
pub(crate) fn concat(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let object = ctx.require_object_coercible(this)?;
let object = this.require_object_coercible(ctx)?;
let mut string = object.to_string(ctx)?.to_string();

for arg in args {
Expand All @@ -221,7 +221,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.repeat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
pub(crate) fn repeat(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let object = ctx.require_object_coercible(this)?;
let object = this.require_object_coercible(ctx)?;
let string = object.to_string(ctx)?;

if let Some(arg) = args.get(0) {
Expand Down Expand Up @@ -563,7 +563,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.indexof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
pub(crate) fn index_of(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let this = ctx.require_object_coercible(this)?;
let this = this.require_object_coercible(ctx)?;
let string = this.to_string(ctx)?;

let search_string = args
Expand Down Expand Up @@ -610,7 +610,7 @@ impl String {
args: &[Value],
ctx: &mut Interpreter,
) -> Result<Value> {
let this = ctx.require_object_coercible(this)?;
let this = this.require_object_coercible(ctx)?;
let string = this.to_string(ctx)?;

let search_string = args
Expand Down Expand Up @@ -776,7 +776,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trim
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
pub(crate) fn trim(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let this = ctx.require_object_coercible(this)?;
let this = this.require_object_coercible(ctx)?;
let string = this.to_string(ctx)?;
Ok(Value::from(
string.trim_matches(Self::is_trimmable_whitespace),
Expand All @@ -796,7 +796,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimstart
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimStart
pub(crate) fn trim_start(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let this = ctx.require_object_coercible(this)?;
let this = this.require_object_coercible(ctx)?;
let string = this.to_string(ctx)?;
Ok(Value::from(
string.trim_start_matches(Self::is_trimmable_whitespace),
Expand All @@ -816,7 +816,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimEnd
pub(crate) fn trim_end(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let this = ctx.require_object_coercible(this)?;
let this = this.require_object_coercible(ctx)?;
let string = this.to_string(ctx)?;
Ok(Value::from(
string.trim_end_matches(Self::is_trimmable_whitespace),
Expand Down
20 changes: 20 additions & 0 deletions boa/src/builtins/value/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,26 @@ impl Value {
}
primitive.to_number(ctx)
}

/// Check if the `Value` can be converted to an `Object`
///
/// The abstract operation `RequireObjectCoercible` takes argument argument.
/// It throws an error if argument is a value that cannot be converted to an Object using `ToObject`.
/// It is defined by [Table 15][table]
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [table]: https://tc39.es/ecma262/#table-14
/// [spec]: https://tc39.es/ecma262/#sec-requireobjectcoercible
#[inline]
pub fn require_object_coercible<'a>(&'a self, ctx: &mut Interpreter) -> Result<&'a Value> {
if self.is_null_or_undefined() {
Err(ctx.construct_type_error("cannot convert null or undefined to Object"))
} else {
Ok(self)
}
}
}

impl Default for Value {
Expand Down
20 changes: 0 additions & 20 deletions boa/src/exec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,26 +333,6 @@ impl Interpreter {
&self.state
}

/// Check if the `Value` can be converted to an `Object`
///
/// The abstract operation `RequireObjectCoercible` takes argument argument.
/// It throws an error if argument is a value that cannot be converted to an Object using `ToObject`.
/// It is defined by [Table 15][table]
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [table]: https://tc39.es/ecma262/#table-14
/// [spec]: https://tc39.es/ecma262/#sec-requireobjectcoercible
#[inline]
pub fn require_object_coercible<'a>(&mut self, value: &'a Value) -> Result<&'a Value> {
if value.is_null_or_undefined() {
Err(self.construct_type_error("cannot convert null or undefined to Object"))
} else {
Ok(value)
}
}

/// A helper function for getting a immutable reference to the `console` object.
pub(crate) fn console(&self) -> &Console {
&self.console
Expand Down

0 comments on commit 7f23537

Please sign in to comment.