- use prototype-less objects where feasible (minor speed improvement)
- get rid of HOP
This commit is contained in:
Mihai Bazon
2012-10-11 11:07:42 +03:00
parent 5053a29bc0
commit 172aa7a93c
5 changed files with 37 additions and 43 deletions

View File

@@ -73,7 +73,7 @@ function DEFNODE(type, props, methods, base) {
if (type) { if (type) {
ctor.prototype.TYPE = ctor.TYPE = type; ctor.prototype.TYPE = ctor.TYPE = type;
} }
if (methods) for (i in methods) if (HOP(methods, i)) { if (methods) for (i in methods) if (methods.hasOwnProperty(i)) {
if (/^\$/.test(i)) { if (/^\$/.test(i)) {
ctor[i.substr(1)] = methods[i]; ctor[i.substr(1)] = methods[i];
} else { } else {

View File

@@ -1449,7 +1449,7 @@ merge(Compressor.prototype, {
OPT(AST_SymbolRef, function(self, compressor){ OPT(AST_SymbolRef, function(self, compressor){
if (self.undeclared()) { if (self.undeclared()) {
var defines = compressor.option("global_defs"); var defines = compressor.option("global_defs");
if (defines && HOP(defines, self.name)) { if (defines && defines.hasOwnProperty(self.name)) {
return make_node_from_constant(compressor, defines[self.name], self); return make_node_from_constant(compressor, defines[self.name], self);
} }
switch (self.name) { switch (self.name) {

View File

@@ -215,9 +215,9 @@ function is_unicode_connector_punctuation(ch) {
function is_identifier(name) { function is_identifier(name) {
return /^[a-z_$][a-z0-9_$]*$/i.test(name) return /^[a-z_$][a-z0-9_$]*$/i.test(name)
&& name != "this" && name != "this"
&& !HOP(KEYWORDS_ATOM, name) && !KEYWORDS_ATOM[name]
&& !HOP(RESERVED_WORDS, name) && !RESERVED_WORDS[name]
&& !HOP(KEYWORDS, name); && !KEYWORDS[name];
}; };
function is_identifier_start(ch) { function is_identifier_start(ch) {
@@ -317,9 +317,9 @@ function tokenizer($TEXT, filename) {
}; };
function token(type, value, is_comment) { function token(type, value, is_comment) {
S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) || S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) ||
(type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) || (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION[value]) ||
(type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value))); (type == "punc" && PUNC_BEFORE_EXPRESSION[value]));
var ret = { var ret = {
type : type, type : type,
value : value, value : value,
@@ -343,7 +343,7 @@ function tokenizer($TEXT, filename) {
}; };
function skip_whitespace() { function skip_whitespace() {
while (HOP(WHITESPACE_CHARS, peek())) while (WHITESPACE_CHARS[peek()])
next(); next();
}; };
@@ -493,7 +493,7 @@ function tokenizer($TEXT, filename) {
backslash = false; backslash = false;
} }
} }
if (HOP(KEYWORDS, name) && escaped) { if (KEYWORDS[name] && escaped) {
hex = name.charCodeAt(0).toString(16).toUpperCase(); hex = name.charCodeAt(0).toString(16).toUpperCase();
name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
} }
@@ -528,7 +528,7 @@ function tokenizer($TEXT, filename) {
function grow(op) { function grow(op) {
if (!peek()) return op; if (!peek()) return op;
var bigger = op + peek(); var bigger = op + peek();
if (HOP(OPERATORS, bigger)) { if (OPERATORS[bigger]) {
next(); next();
return grow(bigger); return grow(bigger);
} else { } else {
@@ -563,11 +563,11 @@ function tokenizer($TEXT, filename) {
function read_word() { function read_word() {
var word = read_name(); var word = read_name();
return HOP(KEYWORDS_ATOM, word) return KEYWORDS_ATOM[word]
? token("atom", word) ? token("atom", word)
: !HOP(KEYWORDS, word) : !KEYWORDS[word]
? token("name", word) ? token("name", word)
: HOP(OPERATORS, word) : OPERATORS[word]
? token("operator", word) ? token("operator", word)
: token("keyword", word); : token("keyword", word);
}; };
@@ -590,10 +590,10 @@ function tokenizer($TEXT, filename) {
if (!ch) return token("eof"); if (!ch) return token("eof");
if (is_digit(ch)) return read_num(); if (is_digit(ch)) return read_num();
if (ch == '"' || ch == "'") return read_string(); if (ch == '"' || ch == "'") return read_string();
if (HOP(PUNC_CHARS, ch)) return token("punc", next()); if (PUNC_CHARS[ch]) return token("punc", next());
if (ch == ".") return handle_dot(); if (ch == ".") return handle_dot();
if (ch == "/") return handle_slash(); if (ch == "/") return handle_slash();
if (HOP(OPERATOR_CHARS, ch)) return read_operator(); if (OPERATOR_CHARS[ch]) return read_operator();
if (ch == "\\" || is_identifier_start(ch)) return read_word(); if (ch == "\\" || is_identifier_start(ch)) return read_word();
parse_error("Unexpected character '" + ch + "'"); parse_error("Unexpected character '" + ch + "'");
}; };
@@ -1200,7 +1200,7 @@ function parse($TEXT, options) {
func.end = prev(); func.end = prev();
return subscripts(func, allow_calls); return subscripts(func, allow_calls);
} }
if (HOP(ATOMIC_START_TOKEN, S.token.type)) { if (ATOMIC_START_TOKEN[S.token.type]) {
return subscripts(as_atom_node(), allow_calls); return subscripts(as_atom_node(), allow_calls);
} }
unexpected(); unexpected();
@@ -1348,7 +1348,7 @@ function parse($TEXT, options) {
var maybe_unary = function(allow_calls) { var maybe_unary = function(allow_calls) {
var start = S.token; var start = S.token;
if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) { if (is("operator") && UNARY_PREFIX[S.token.value]) {
var ex = make_unary(AST_UnaryPrefix, var ex = make_unary(AST_UnaryPrefix,
prog1(S.token.value, next), prog1(S.token.value, next),
maybe_unary(allow_calls)); maybe_unary(allow_calls));
@@ -1357,7 +1357,7 @@ function parse($TEXT, options) {
return ex; return ex;
} }
var val = expr_atom(allow_calls); var val = expr_atom(allow_calls);
while (is("operator") && HOP(UNARY_POSTFIX, S.token.value) && !S.token.nlb) { while (is("operator") && UNARY_POSTFIX[S.token.value] && !S.token.nlb) {
val = make_unary(AST_UnaryPostfix, S.token.value, val); val = make_unary(AST_UnaryPostfix, S.token.value, val);
val.start = start; val.start = start;
val.end = S.token; val.end = S.token;
@@ -1428,7 +1428,7 @@ function parse($TEXT, options) {
var maybe_assign = function(no_in) { var maybe_assign = function(no_in) {
var start = S.token; var start = S.token;
var left = maybe_conditional(no_in), val = S.token.value; var left = maybe_conditional(no_in), val = S.token.value;
if (is("operator") && HOP(ASSIGNMENT, val)) { if (is("operator") && ASSIGNMENT[val]) {
if (is_assignable(left)) { if (is_assignable(left)) {
next(); next();
return new AST_Assign({ return new AST_Assign({

View File

@@ -75,7 +75,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
// pass 1: setup scope chaining and handle definitions // pass 1: setup scope chaining and handle definitions
var self = this; var self = this;
var scope = self.parent_scope = null; var scope = self.parent_scope = null;
var labels = {}; var labels = Object.create(null);
var tw = new TreeWalker(function(node, descend){ var tw = new TreeWalker(function(node, descend){
if (node instanceof AST_Scope) { if (node instanceof AST_Scope) {
node.init_scope_vars(); node.init_scope_vars();
@@ -157,7 +157,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
// pass 2: find back references and eval // pass 2: find back references and eval
var func = null; var func = null;
var globals = self.globals = {}; var globals = self.globals = Object.create(null);
var tw = new TreeWalker(function(node, descend){ var tw = new TreeWalker(function(node, descend){
if (node instanceof AST_Lambda) { if (node instanceof AST_Lambda) {
var prev_func = func; var prev_func = func;
@@ -175,7 +175,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
var sym = node.scope.find_variable(name); var sym = node.scope.find_variable(name);
if (!sym) { if (!sym) {
var g; var g;
if (HOP(globals, name)) { if (globals[name]) {
g = globals[name]; g = globals[name];
} else { } else {
g = new SymbolDef(self, node); g = new SymbolDef(self, node);
@@ -202,8 +202,8 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
AST_Scope.DEFMETHOD("init_scope_vars", function(){ AST_Scope.DEFMETHOD("init_scope_vars", function(){
this.directives = []; // contains the directives defined in this scope, i.e. "use strict" this.directives = []; // contains the directives defined in this scope, i.e. "use strict"
this.variables = {}; // map name to AST_SymbolVar (variables defined in this scope; includes functions) this.variables = Object.create(null); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
this.functions = {}; // map name to AST_SymbolDefun (functions defined in this scope) this.functions = Object.create(null); // map name to AST_SymbolDefun (functions defined in this scope)
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
this.parent_scope = null; // the parent scope this.parent_scope = null; // the parent scope
@@ -245,9 +245,8 @@ AST_LabelRef.DEFMETHOD("reference", function(){
AST_Scope.DEFMETHOD("find_variable", function(name){ AST_Scope.DEFMETHOD("find_variable", function(name){
if (name instanceof AST_Symbol) name = name.name; if (name instanceof AST_Symbol) name = name.name;
return HOP(this.variables, name) return this.variables[name]
? this.variables[name] || (this.parent_scope && this.parent_scope.find_variable(name));
: (this.parent_scope && this.parent_scope.find_variable(name));
}); });
AST_Scope.DEFMETHOD("has_directive", function(value){ AST_Scope.DEFMETHOD("has_directive", function(value){
@@ -261,7 +260,7 @@ AST_Scope.DEFMETHOD("def_function", function(symbol){
AST_Scope.DEFMETHOD("def_variable", function(symbol){ AST_Scope.DEFMETHOD("def_variable", function(symbol){
var def; var def;
if (!HOP(this.variables, symbol.name)) { if (!this.variables[symbol.name]) {
def = new SymbolDef(this, symbol); def = new SymbolDef(this, symbol);
this.variables[symbol.name] = def; this.variables[symbol.name] = def;
def.global = !this.parent_scope; def.global = !this.parent_scope;
@@ -351,7 +350,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
var p = tw.parent(); var p = tw.parent();
var is_setget = p instanceof AST_ObjectSetter || p instanceof AST_ObjectGetter; var is_setget = p instanceof AST_ObjectSetter || p instanceof AST_ObjectGetter;
var a = node.variables; var a = node.variables;
for (var i in a) if (HOP(a, i)) { for (var i in a) {
var symbol = a[i]; var symbol = a[i];
if (!(is_setget && symbol instanceof AST_SymbolLambda)) { if (!(is_setget && symbol instanceof AST_SymbolLambda)) {
if (options.except.indexOf(symbol.name) < 0) { if (options.except.indexOf(symbol.name) < 0) {
@@ -450,15 +449,14 @@ var base54 = (function() {
var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
var chars, frequency; var chars, frequency;
function reset() { function reset() {
frequency = {}; frequency = Object.create(null);
chars = string.split(""); chars = string.split("");
chars.map(function(ch){ frequency[ch] = 0 }); chars.map(function(ch){ frequency[ch] = 0 });
} }
base54.consider = function(str){ base54.consider = function(str){
for (var i = str.length; --i >= 0;) { for (var i = str.length; --i >= 0;) {
var ch = str.charAt(i); var ch = str.charAt(i);
if (string.indexOf(ch) >= 0) ++frequency[ch];
++frequency[ch];
} }
}; };
base54.sort = function() { base54.sort = function() {

View File

@@ -57,7 +57,7 @@ function prog1(ret) {
}; };
function array_to_hash(a) { function array_to_hash(a) {
var ret = {}; var ret = Object.create(null);
for (var i = 0; i < a.length; ++i) for (var i = 0; i < a.length; ++i)
ret[a[i]] = true; ret[a[i]] = true;
return ret; return ret;
@@ -85,10 +85,6 @@ function find_if(func, array) {
} }
}; };
function HOP(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
};
function repeat_string(str, i) { function repeat_string(str, i) {
if (i <= 0) return ""; if (i <= 0) return "";
if (i == 1) return str; if (i == 1) return str;
@@ -107,16 +103,16 @@ function defaults(args, defs, croak) {
if (args === true) if (args === true)
args = {}; args = {};
var ret = args || {}; var ret = args || {};
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i)) if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i))
throw new DefaultsError("`" + i + "` is not a supported option", defs); throw new DefaultsError("`" + i + "` is not a supported option", defs);
for (var i in defs) if (HOP(defs, i)) { for (var i in defs) if (defs.hasOwnProperty(i)) {
ret[i] = (args && HOP(args, i)) ? args[i] : defs[i]; ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i];
} }
return ret; return ret;
}; };
function merge(obj, ext) { function merge(obj, ext) {
for (var i in ext) if (HOP(ext, i)) { for (var i in ext) if (ext.hasOwnProperty(i)) {
obj[i] = ext[i]; obj[i] = ext[i];
} }
return obj; return obj;
@@ -158,7 +154,7 @@ var MAP = (function(){
} }
} }
else { else {
for (i in a) if (HOP(a, i)) if (doit()) break; for (i in a) if (a.hasOwnProperty(i)) if (doit()) break;
} }
return top.concat(ret); return top.concat(ret);
}; };