#include "src/allocation.h"
#include "src/ast.h"
#include "src/compiler.h" // For CachedDataMode
-#include "src/preparse-data-format.h"
#include "src/preparse-data.h"
-#include "src/scopes.h"
+#include "src/preparse-data-format.h"
#include "src/preparser.h"
+#include "src/scopes.h"
namespace v8 {
class ScriptCompiler;
int literal_count() { return backing_[kLiteralCountIndex]; }
int property_count() { return backing_[kPropertyCountIndex]; }
StrictMode strict_mode() {
- ASSERT(backing_[kStrictModeIndex] == SLOPPY ||
+ DCHECK(backing_[kStrictModeIndex] == SLOPPY ||
backing_[kStrictModeIndex] == STRICT);
return static_cast<StrictMode>(backing_[kStrictModeIndex]);
}
};
-class ScriptData {
+// Wrapper around ScriptData to provide parser-specific functionality.
+class ParseData {
public:
- explicit ScriptData(Vector<unsigned> store)
- : store_(store),
- owns_store_(true) { }
-
- ScriptData(Vector<unsigned> store, bool owns_store)
- : store_(store),
- owns_store_(owns_store) { }
-
- // The created ScriptData won't take ownership of the data. If the alignment
- // is not correct, this will copy the data (and the created ScriptData will
- // take ownership of the copy).
- static ScriptData* New(const char* data, int length);
-
- virtual ~ScriptData();
- virtual int Length();
- virtual const char* Data();
- virtual bool HasError();
-
+ explicit ParseData(ScriptData* script_data) : script_data_(script_data) {
+ CHECK(IsAligned(script_data->length(), sizeof(unsigned)));
+ CHECK(IsSane());
+ }
void Initialize();
- void ReadNextSymbolPosition();
-
FunctionEntry GetFunctionEntry(int start);
- int GetSymbolIdentifier();
- bool SanityCheck();
-
- Scanner::Location MessageLocation() const;
- bool IsReferenceError() const;
- const char* BuildMessage() const;
- const char* BuildArg() const;
-
- int function_count() {
- int functions_size =
- static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
- if (functions_size < 0) return 0;
- if (functions_size % FunctionEntry::kSize != 0) return 0;
- return functions_size / FunctionEntry::kSize;
+ int FunctionCount();
+
+ bool HasError();
+
+ unsigned* Data() { // Writable data as unsigned int array.
+ return reinterpret_cast<unsigned*>(const_cast<byte*>(script_data_->data()));
}
- // The following functions should only be called if SanityCheck has
- // returned true.
- bool has_error() { return store_[PreparseDataConstants::kHasErrorOffset]; }
- unsigned magic() { return store_[PreparseDataConstants::kMagicOffset]; }
- unsigned version() { return store_[PreparseDataConstants::kVersionOffset]; }
private:
- // Disable copying and assigning; because of owns_store they won't be correct.
- ScriptData(const ScriptData&);
- ScriptData& operator=(const ScriptData&);
-
- friend class v8::ScriptCompiler;
- Vector<unsigned> store_;
- unsigned char* symbol_data_;
- unsigned char* symbol_data_end_;
- int function_index_;
- bool owns_store_;
+ bool IsSane();
+ unsigned Magic();
+ unsigned Version();
+ int FunctionsSize();
+ int Length() const {
+ // Script data length is already checked to be a multiple of unsigned size.
+ return script_data_->length() / sizeof(unsigned);
+ }
- unsigned Read(int position) const;
- unsigned* ReadAddress(int position) const;
- // Reads a number from the current symbols
- int ReadNumber(byte** source);
+ ScriptData* script_data_;
+ int function_index_;
- // Read strings written by ParserRecorder::WriteString.
- static const char* ReadString(unsigned* start, int* chars);
+ DISALLOW_COPY_AND_ASSIGN(ParseData);
};
-
// ----------------------------------------------------------------------------
// REGEXP PARSING
}
T* last() {
- ASSERT(last_ != NULL);
+ DCHECK(last_ != NULL);
return last_;
}
T* RemoveLast() {
- ASSERT(last_ != NULL);
+ DCHECK(last_ != NULL);
T* result = last_;
if ((list_ != NULL) && (list_->length() > 0))
last_ = list_->RemoveLast();
}
T* Get(int i) {
- ASSERT((0 <= i) && (i < length()));
+ DCHECK((0 <= i) && (i < length()));
if (list_ == NULL) {
- ASSERT_EQ(0, i);
+ DCHECK_EQ(0, i);
return last_;
} else {
if (i == list_->length()) {
- ASSERT(last_ != NULL);
+ DCHECK(last_ != NULL);
return last_;
} else {
return list_->at(i);
// Used by FunctionState and BlockState.
typedef v8::internal::Scope Scope;
+ typedef v8::internal::Scope* ScopePtr;
typedef Variable GeneratorVariable;
typedef v8::internal::Zone Zone;
+ class Checkpoint BASE_EMBEDDED {
+ public:
+ template <typename Parser>
+ explicit Checkpoint(Parser* parser) {
+ isolate_ = parser->zone()->isolate();
+ saved_ast_node_id_ = isolate_->ast_node_id();
+ }
+
+ void Restore() { isolate_->set_ast_node_id(saved_ast_node_id_); }
+
+ private:
+ Isolate* isolate_;
+ int saved_ast_node_id_;
+ };
+
+ typedef v8::internal::AstProperties AstProperties;
+ typedef Vector<VariableProxy*> ParameterIdentifierVector;
+
// Return types for traversing functions.
- typedef Handle<String> Identifier;
+ typedef const AstRawString* Identifier;
typedef v8::internal::Expression* Expression;
typedef Yield* YieldExpression;
typedef v8::internal::FunctionLiteral* FunctionLiteral;
}
// Helper functions for recursive descent.
- bool IsEvalOrArguments(Handle<String> identifier) const;
+ bool IsEvalOrArguments(const AstRawString* identifier) const;
+ V8_INLINE bool IsFutureStrictReserved(const AstRawString* identifier) const;
// Returns true if the expression is of type "this.foo".
static bool IsThisProperty(Expression* expression);
static bool IsIdentifier(Expression* expression);
- static Handle<String> AsIdentifier(Expression* expression) {
- ASSERT(IsIdentifier(expression));
- return expression->AsVariableProxy()->name();
+ static const AstRawString* AsIdentifier(Expression* expression) {
+ DCHECK(IsIdentifier(expression));
+ return expression->AsVariableProxy()->raw_name();
}
static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
return ObjectLiteral::IsBoilerplateProperty(property);
}
- static bool IsArrayIndex(Handle<String> string, uint32_t* index) {
- return !string.is_null() && string->AsArrayIndex(index);
+ static bool IsArrayIndex(const AstRawString* string, uint32_t* index) {
+ return string->AsArrayIndex(index);
}
// Functions for encapsulating the differences between parsing and preparsing;
// operations interleaved with the recursive descent.
- static void PushLiteralName(FuncNameInferrer* fni, Handle<String> id) {
+ static void PushLiteralName(FuncNameInferrer* fni, const AstRawString* id) {
fni->PushLiteralName(id);
}
void PushPropertyName(FuncNameInferrer* fni, Expression* expression);
+ static void InferFunctionName(FuncNameInferrer* fni,
+ FunctionLiteral* func_to_infer) {
+ fni->AddFunction(func_to_infer);
+ }
static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
Scope* scope, Expression* value, bool* has_function) {
void CheckPossibleEvalCall(Expression* expression, Scope* scope);
// Determine if the expression is a variable proxy and mark it as being used
- // in an assignment or with a increment/decrement operator. This is currently
- // used on for the statically checking assignments to harmony const bindings.
- static Expression* MarkExpressionAsLValue(Expression* expression);
+ // in an assignment or with a increment/decrement operator.
+ static Expression* MarkExpressionAsAssigned(Expression* expression);
// Returns true if we have a binary expression between two numeric
// literals. In that case, *x will be changed to an expression which is the
// type. The first argument may be null (in the handle sense) in
// which case no arguments are passed to the constructor.
Expression* NewThrowSyntaxError(
- const char* type, Handle<Object> arg, int pos);
+ const char* type, const AstRawString* arg, int pos);
// Generate AST node that throws a TypeError with the given
// type. Both arguments must be non-null (in the handle sense).
- Expression* NewThrowTypeError(const char* type, Handle<Object> arg, int pos);
+ Expression* NewThrowTypeError(const char* type, const AstRawString* arg,
+ int pos);
// Generic AST generator for throwing errors from compiled code.
Expression* NewThrowError(
- Handle<String> constructor, const char* type,
- Vector<Handle<Object> > arguments, int pos);
+ const AstRawString* constructor, const char* type,
+ const AstRawString* arg, int pos);
// Reporting errors.
void ReportMessageAt(Scanner::Location source_location,
const char* message,
- const char* arg,
+ const char* arg = NULL,
bool is_reference_error = false);
void ReportMessage(const char* message,
- MaybeHandle<String> arg,
+ const char* arg = NULL,
+ bool is_reference_error = false);
+ void ReportMessage(const char* message,
+ const AstRawString* arg,
bool is_reference_error = false);
void ReportMessageAt(Scanner::Location source_location,
const char* message,
- MaybeHandle<String> arg,
+ const AstRawString* arg,
bool is_reference_error = false);
// "null" return type creators.
- static Handle<String> EmptyIdentifier() {
- return Handle<String>();
+ static const AstRawString* EmptyIdentifier() {
+ return NULL;
}
static Expression* EmptyExpression() {
return NULL;
}
+ static Expression* EmptyArrowParamList() { return NULL; }
static Literal* EmptyLiteral() {
return NULL;
}
+
// Used in error return values.
static ZoneList<Expression*>* NullExpressionList() {
return NULL;
}
+ // Non-NULL empty string.
+ V8_INLINE const AstRawString* EmptyIdentifierString();
+
// Odd-ball literal creators.
Literal* GetLiteralTheHole(int position,
AstNodeFactory<AstConstructionVisitor>* factory);
// Producing data during the recursive descent.
- Handle<String> GetSymbol(Scanner* scanner = NULL);
- Handle<String> NextLiteralString(Scanner* scanner,
- PretenureFlag tenured);
+ const AstRawString* GetSymbol(Scanner* scanner);
+ const AstRawString* GetNextSymbol(Scanner* scanner);
+
Expression* ThisExpression(Scope* scope,
- AstNodeFactory<AstConstructionVisitor>* factory);
+ AstNodeFactory<AstConstructionVisitor>* factory,
+ int pos = RelocInfo::kNoPosition);
Literal* ExpressionFromLiteral(
Token::Value token, int pos, Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory);
Expression* ExpressionFromIdentifier(
- Handle<String> name, int pos, Scope* scope,
+ const AstRawString* name, int pos, Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory);
Expression* ExpressionFromString(
int pos, Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory);
+ Expression* GetIterator(Expression* iterable,
+ AstNodeFactory<AstConstructionVisitor>* factory);
ZoneList<v8::internal::Expression*>* NewExpressionList(int size, Zone* zone) {
return new(zone) ZoneList<v8::internal::Expression*>(size, zone);
}
ZoneList<v8::internal::Statement*>* NewStatementList(int size, Zone* zone) {
return new(zone) ZoneList<v8::internal::Statement*>(size, zone);
}
+ V8_INLINE Scope* NewScope(Scope* parent_scope, ScopeType scope_type);
+
+ // Utility functions
+ int DeclareArrowParametersFromExpression(Expression* expression, Scope* scope,
+ Scanner::Location* dupe_loc,
+ bool* ok);
+ V8_INLINE AstValueFactory* ast_value_factory();
// Temporary glue; these functions will move to ParserBase.
Expression* ParseV8Intrinsic(bool* ok);
FunctionLiteral* ParseFunctionLiteral(
- Handle<String> name,
+ const AstRawString* name,
Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
FunctionLiteral::FunctionType type,
FunctionLiteral::ArityRestriction arity_restriction,
bool* ok);
+ V8_INLINE void SkipLazyFunctionBody(const AstRawString* name,
+ int* materialized_literal_count,
+ int* expected_property_count, bool* ok);
+ V8_INLINE ZoneList<Statement*>* ParseEagerFunctionBody(
+ const AstRawString* name, int pos, Variable* fvar,
+ Token::Value fvar_init_op, bool is_generator, bool* ok);
+ V8_INLINE void CheckConflictingVarDeclarations(v8::internal::Scope* scope,
+ bool* ok);
private:
Parser* parser_;
~Parser() {
delete reusable_preparser_;
reusable_preparser_ = NULL;
+ delete cached_parse_data_;
+ cached_parse_data_ = NULL;
}
// Parses the source code represented by the compilation info and sets its
FunctionLiteral* DoParseProgram(CompilationInfo* info,
Handle<String> source);
- // Report syntax error
- void ReportInvalidCachedData(Handle<String> name, bool* ok);
-
- void SetCachedData(ScriptData** data,
- CachedDataMode cached_data_mode) {
- cached_data_mode_ = cached_data_mode;
- if (cached_data_mode == NO_CACHED_DATA) {
- cached_data_ = NULL;
- } else {
- ASSERT(data != NULL);
- cached_data_ = data;
- }
- }
+ void SetCachedData();
bool inside_with() const { return scope_->inside_with(); }
- ScriptData** cached_data() const { return cached_data_; }
- CachedDataMode cached_data_mode() const { return cached_data_mode_; }
+ ScriptCompiler::CompileOptions compile_options() const {
+ return info_->compile_options();
+ }
Scope* DeclarationScope(VariableMode mode) {
return IsLexicalVariableMode(mode)
? scope_ : scope_->DeclarationScope();
// for failure at the call sites.
void* ParseSourceElements(ZoneList<Statement*>* processor, int end_token,
bool is_eval, bool is_global, bool* ok);
- Statement* ParseModuleElement(ZoneStringList* labels, bool* ok);
- Statement* ParseModuleDeclaration(ZoneStringList* names, bool* ok);
+ Statement* ParseModuleElement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
+ Statement* ParseModuleDeclaration(ZoneList<const AstRawString*>* names,
+ bool* ok);
Module* ParseModule(bool* ok);
Module* ParseModuleLiteral(bool* ok);
Module* ParseModulePath(bool* ok);
Module* ParseModuleSpecifier(bool* ok);
Block* ParseImportDeclaration(bool* ok);
Statement* ParseExportDeclaration(bool* ok);
- Statement* ParseBlockElement(ZoneStringList* labels, bool* ok);
- Statement* ParseStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseFunctionDeclaration(ZoneStringList* names, bool* ok);
+ Statement* ParseBlockElement(ZoneList<const AstRawString*>* labels, bool* ok);
+ Statement* ParseStatement(ZoneList<const AstRawString*>* labels, bool* ok);
+ Statement* ParseFunctionDeclaration(ZoneList<const AstRawString*>* names,
+ bool* ok);
Statement* ParseNativeDeclaration(bool* ok);
- Block* ParseBlock(ZoneStringList* labels, bool* ok);
+ Block* ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok);
Block* ParseVariableStatement(VariableDeclarationContext var_context,
- ZoneStringList* names,
+ ZoneList<const AstRawString*>* names,
bool* ok);
Block* ParseVariableDeclarations(VariableDeclarationContext var_context,
VariableDeclarationProperties* decl_props,
- ZoneStringList* names,
- Handle<String>* out,
+ ZoneList<const AstRawString*>* names,
+ const AstRawString** out,
bool* ok);
- Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels,
- bool* ok);
- IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseExpressionOrLabelledStatement(
+ ZoneList<const AstRawString*>* labels, bool* ok);
+ IfStatement* ParseIfStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
Statement* ParseContinueStatement(bool* ok);
- Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseBreakStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
Statement* ParseReturnStatement(bool* ok);
- Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseWithStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
- SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
- DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok);
- WhileStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseForStatement(ZoneStringList* labels, bool* ok);
+ SwitchStatement* ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
+ DoWhileStatement* ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
+ WhileStatement* ParseWhileStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
+ Statement* ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement* ParseThrowStatement(bool* ok);
Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
TryStatement* ParseTryStatement(bool* ok);
DebuggerStatement* ParseDebuggerStatement(bool* ok);
// Support for hamony block scoped bindings.
- Block* ParseScopedBlock(ZoneStringList* labels, bool* ok);
+ Block* ParseScopedBlock(ZoneList<const AstRawString*>* labels, bool* ok);
// Initialize the components of a for-in / for-of statement.
void InitializeForEachStatement(ForEachStatement* stmt,
Expression* subject,
Statement* body);
Statement* DesugarLetBindingsInForStatement(
- Scope* inner_scope, ZoneStringList* names, ForStatement* loop,
- Statement* init, Expression* cond, Statement* next, Statement* body,
- bool* ok);
+ Scope* inner_scope, ZoneList<const AstRawString*>* names,
+ ForStatement* loop, Statement* init, Expression* cond, Statement* next,
+ Statement* body, bool* ok);
FunctionLiteral* ParseFunctionLiteral(
- Handle<String> name,
+ const AstRawString* name,
Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
void CheckConflictingVarDeclarations(Scope* scope, bool* ok);
// Parser support
- VariableProxy* NewUnresolved(Handle<String> name,
+ VariableProxy* NewUnresolved(const AstRawString* name,
VariableMode mode,
Interface* interface);
void Declare(Declaration* declaration, bool resolve, bool* ok);
- bool TargetStackContainsLabel(Handle<String> label);
- BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
- IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok);
+ bool TargetStackContainsLabel(const AstRawString* label);
+ BreakableStatement* LookupBreakTarget(const AstRawString* label, bool* ok);
+ IterationStatement* LookupContinueTarget(const AstRawString* label, bool* ok);
void RegisterTargetUse(Label* target, Target* stop);
// Skip over a lazy function, either using cached data if we have it, or
// by parsing the function with PreParser. Consumes the ending }.
- void SkipLazyFunctionBody(Handle<String> function_name,
+ void SkipLazyFunctionBody(const AstRawString* function_name,
int* materialized_literal_count,
int* expected_property_count,
bool* ok);
SingletonLogger* logger);
// Consumes the ending }.
- ZoneList<Statement*>* ParseEagerFunctionBody(Handle<String> function_name,
- int pos,
- Variable* fvar,
- Token::Value fvar_init_op,
- bool is_generator,
- bool* ok);
+ ZoneList<Statement*>* ParseEagerFunctionBody(
+ const AstRawString* function_name, int pos, Variable* fvar,
+ Token::Value fvar_init_op, bool is_generator, bool* ok);
+
+ void HandleSourceURLComments();
void ThrowPendingError();
+ void InternalizeUseCounts();
+
Isolate* isolate_;
Handle<Script> script_;
PreParser* reusable_preparser_;
Scope* original_scope_; // for ES5 function declarations in sloppy eval
Target* target_stack_; // for break, continue statements
- ScriptData** cached_data_;
- CachedDataMode cached_data_mode_;
+ ParseData* cached_parse_data_;
+ AstValueFactory* ast_value_factory_;
CompilationInfo* info_;
bool has_pending_error_;
Scanner::Location pending_error_location_;
const char* pending_error_message_;
- MaybeHandle<String> pending_error_arg_;
+ const AstRawString* pending_error_arg_;
const char* pending_error_char_arg_;
bool pending_error_is_reference_error_;
+
+ int use_counts_[v8::Isolate::kUseCounterFeatureCount];
};
+bool ParserTraits::IsFutureStrictReserved(
+ const AstRawString* identifier) const {
+ return identifier->IsOneByteEqualTo("yield") ||
+ parser_->scanner()->IdentifierIsFutureStrictReserved(identifier);
+}
+
+
+Scope* ParserTraits::NewScope(Scope* parent_scope, ScopeType scope_type) {
+ return parser_->NewScope(parent_scope, scope_type);
+}
+
+
+const AstRawString* ParserTraits::EmptyIdentifierString() {
+ return parser_->ast_value_factory_->empty_string();
+}
+
+
+void ParserTraits::SkipLazyFunctionBody(const AstRawString* function_name,
+ int* materialized_literal_count,
+ int* expected_property_count,
+ bool* ok) {
+ return parser_->SkipLazyFunctionBody(
+ function_name, materialized_literal_count, expected_property_count, ok);
+}
+
+
+ZoneList<Statement*>* ParserTraits::ParseEagerFunctionBody(
+ const AstRawString* name, int pos, Variable* fvar,
+ Token::Value fvar_init_op, bool is_generator, bool* ok) {
+ return parser_->ParseEagerFunctionBody(name, pos, fvar, fvar_init_op,
+ is_generator, ok);
+}
+
+void ParserTraits::CheckConflictingVarDeclarations(v8::internal::Scope* scope,
+ bool* ok) {
+ parser_->CheckConflictingVarDeclarations(scope, ok);
+}
+
+
+AstValueFactory* ParserTraits::ast_value_factory() {
+ return parser_->ast_value_factory_;
+}
+
+
// Support for handling complex values (array and object literals) that
// can be fully handled at compile time.
class CompileTimeValue: public AllStatic {