Index: src/parser.h |
diff --git a/src/parser.h b/src/parser.h |
index 19b382e8ded3442c794dc57c2ab17f337aee39ff..667410b3ce3e459da2862532c751bd1f7e4fcea9 100644 |
--- a/src/parser.h |
+++ b/src/parser.h |
@@ -31,13 +31,13 @@ |
#include "allocation.h" |
#include "ast.h" |
#include "scanner.h" |
+#include "scopes.h" |
namespace v8 { |
namespace internal { |
class CompilationInfo; |
class FuncNameInferrer; |
-class ParserFactory; |
class ParserLog; |
class PositionStack; |
class Target; |
@@ -177,6 +177,125 @@ class ScriptDataImpl : public ScriptData { |
}; |
+// Record only functions. |
+class PartialParserRecorder { |
+ public: |
+ PartialParserRecorder(); |
+ |
+ void LogFunction(int start, int end, int literals, int properties) { |
+ function_store_.Add(start); |
+ function_store_.Add(end); |
+ function_store_.Add(literals); |
+ function_store_.Add(properties); |
+ } |
+ |
+ void LogSymbol(int start, const char* symbol, int length) { } |
+ |
+ // Logs an error message and marks the log as containing an error. |
+ // Further logging will be ignored, and ExtractData will return a vector |
+ // representing the error only. |
+ void LogMessage(int start, |
+ int end, |
+ const char* message, |
+ const char* argument_opt) { |
+ Scanner::Location location(start, end); |
+ Vector<const char*> arguments; |
+ if (argument_opt != NULL) { |
+ arguments = Vector<const char*>(&argument_opt, 1); |
+ } |
+ this->LogMessage(location, message, arguments); |
+ } |
+ |
+ int function_position() { return function_store_.size(); } |
+ |
+ void LogMessage(Scanner::Location loc, |
+ const char* message, |
+ Vector<const char*> args); |
+ |
+ Vector<unsigned> ExtractData(); |
+ |
+ void PauseRecording() { |
+ pause_count_++; |
+ is_recording_ = false; |
+ } |
+ |
+ void ResumeRecording() { |
+ ASSERT(pause_count_ > 0); |
+ if (--pause_count_ == 0) is_recording_ = !has_error(); |
+ } |
+ |
+ int symbol_position() { return 0; } |
+ int symbol_ids() { return 0; } |
+ |
+ protected: |
+ bool has_error() { |
+ return static_cast<bool>(preamble_[ScriptDataImpl::kHasErrorOffset]); |
+ } |
+ |
+ bool is_recording() { |
+ return is_recording_; |
+ } |
+ |
+ void WriteString(Vector<const char> str); |
+ |
+ Collector<unsigned> function_store_; |
+ unsigned preamble_[ScriptDataImpl::kHeaderSize]; |
+ bool is_recording_; |
+ int pause_count_; |
+ |
+#ifdef DEBUG |
+ int prev_start_; |
+#endif |
+}; |
+ |
+ |
+// Record both functions and symbols. |
+class CompleteParserRecorder: public PartialParserRecorder { |
+ public: |
+ CompleteParserRecorder(); |
+ |
+ void LogSymbol(int start, Vector<const char> literal); |
+ |
+ void LogSymbol(int start, const char* symbol, int length) { |
+ LogSymbol(start, Vector<const char>(symbol, length)); |
+ } |
+ |
+ Vector<unsigned> ExtractData(); |
+ |
+ int symbol_position() { return symbol_store_.size(); } |
+ int symbol_ids() { return symbol_id_; } |
+ |
+ private: |
+ static int vector_hash(Vector<const char> string) { |
+ int hash = 0; |
+ for (int i = 0; i < string.length(); i++) { |
+ int c = string[i]; |
+ hash += c; |
+ hash += (hash << 10); |
+ hash ^= (hash >> 6); |
+ } |
+ return hash; |
+ } |
+ |
+ static bool vector_compare(void* a, void* b) { |
+ Vector<const char>* string1 = reinterpret_cast<Vector<const char>* >(a); |
+ Vector<const char>* string2 = reinterpret_cast<Vector<const char>* >(b); |
+ int length = string1->length(); |
+ if (string2->length() != length) return false; |
+ return memcmp(string1->start(), string2->start(), length) == 0; |
+ } |
+ |
+ // Write a non-negative number to the symbol store. |
+ void WriteNumber(int number); |
+ |
+ Collector<byte> symbol_store_; |
+ Collector<Vector<const char> > symbol_entries_; |
+ HashMap symbol_table_; |
+ int symbol_id_; |
+}; |
+ |
+ |
+ |
class ParserApi { |
public: |
// Parses the source code represented by the compilation info and sets its |
@@ -196,6 +315,8 @@ class ParserApi { |
v8::Extension* extension); |
}; |
+// ---------------------------------------------------------------------------- |
+// REGEXP PARSING |
// A BuffferedZoneList is an automatically growing list, just like (and backed |
// by) a ZoneList, that is optimized for the case of adding and removing |
@@ -411,51 +532,44 @@ class RegExpParser { |
uc32 Next(); |
FlatStringReader* in() { return in_; } |
void ScanForCaptures(); |
+ |
+ Handle<String>* error_; |
+ ZoneList<RegExpCapture*>* captures_; |
+ FlatStringReader* in_; |
uc32 current_; |
+ int next_pos_; |
+ // The capture count is only valid after we have scanned for captures. |
+ int capture_count_; |
bool has_more_; |
bool multiline_; |
- int next_pos_; |
- FlatStringReader* in_; |
- Handle<String>* error_; |
bool simple_; |
bool contains_anchor_; |
- ZoneList<RegExpCapture*>* captures_; |
bool is_scanned_for_captures_; |
- // The capture count is only valid after we have scanned for captures. |
- int capture_count_; |
bool failed_; |
}; |
+// ---------------------------------------------------------------------------- |
+// JAVASCRIPT PARSING |
class Parser { |
public: |
- Parser(Handle<Script> script, bool allow_natives_syntax, |
- v8::Extension* extension, ParserMode is_pre_parsing, |
- ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data); |
+ Parser(Handle<Script> script, |
+ bool allow_natives_syntax, |
+ v8::Extension* extension, |
+ ScriptDataImpl* pre_data); |
virtual ~Parser() { } |
- // Pre-parse the program from the character stream; returns true on |
- // success, false if a stack-overflow happened during parsing. |
- bool PreParseProgram(Handle<String> source, unibrow::CharacterStream* stream); |
- |
- void ReportMessage(const char* message, Vector<const char*> args); |
- virtual void ReportMessageAt(Scanner::Location loc, |
- const char* message, |
- Vector<const char*> args) = 0; |
- |
- |
// Returns NULL if parsing failed. |
FunctionLiteral* ParseProgram(Handle<String> source, |
bool in_global_context); |
+ |
FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info); |
- // The minimum number of contiguous assignment that will |
- // be treated as an initialization block. Benchmarks show that |
- // the overhead exceeds the savings below this limit. |
- static const int kMinInitializationBlock = 3; |
+ void ReportMessageAt(Scanner::Location loc, |
+ const char* message, |
+ Vector<const char*> args); |
protected: |
- |
enum Mode { |
PARSE_LAZILY, |
PARSE_EAGERLY |
@@ -464,28 +578,9 @@ class Parser { |
// Report syntax error |
void ReportUnexpectedToken(Token::Value token); |
void ReportInvalidPreparseData(Handle<String> name, bool* ok); |
- |
- Handle<Script> script_; |
- Scanner scanner_; |
- |
- Scope* top_scope_; |
- int with_nesting_level_; |
- |
- TemporaryScope* temp_scope_; |
- Mode mode_; |
- |
- Target* target_stack_; // for break, continue statements |
- bool allow_natives_syntax_; |
- v8::Extension* extension_; |
- ParserFactory* factory_; |
- ParserLog* log_; |
- bool is_pre_parsing_; |
- ScriptDataImpl* pre_data_; |
- FuncNameInferrer* fni_; |
+ void ReportMessage(const char* message, Vector<const char*> args); |
bool inside_with() const { return with_nesting_level_ > 0; } |
- ParserFactory* factory() const { return factory_; } |
- ParserLog* log() const { return log_; } |
Scanner& scanner() { return scanner_; } |
Mode mode() const { return mode_; } |
ScriptDataImpl* pre_data() const { return pre_data_; } |
@@ -494,7 +589,7 @@ class Parser { |
// which is set to false if parsing failed; it is unchanged otherwise. |
// By making the 'exception handling' explicit, we are forced to check |
// for failure at the call sites. |
- void* ParseSourceElements(ZoneListWrapper<Statement>* processor, |
+ void* ParseSourceElements(ZoneList<Statement*>* processor, |
int end_token, bool* ok); |
Statement* ParseStatement(ZoneStringList* labels, bool* ok); |
Statement* ParseFunctionDeclaration(bool* ok); |
@@ -607,10 +702,10 @@ class Parser { |
bool* ok); |
// Parser support |
- virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode, |
- FunctionLiteral* fun, |
- bool resolve, |
- bool* ok) = 0; |
+ VariableProxy* Declare(Handle<String> name, Variable::Mode mode, |
+ FunctionLiteral* fun, |
+ bool resolve, |
+ bool* ok); |
bool TargetStackContainsLabel(Handle<String> label); |
BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok); |
@@ -618,6 +713,28 @@ class Parser { |
void RegisterTargetUse(BreakTarget* target, Target* stop); |
+ // Factory methods. |
+ |
+ Statement* EmptyStatement() { |
+ static v8::internal::EmptyStatement empty; |
+ return ∅ |
+ } |
+ |
+ Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with); |
+ |
+ Handle<String> LookupSymbol(int symbol_id, |
+ Vector<const char> string); |
+ |
+ Handle<String> LookupCachedSymbol(int symbol_id, |
+ Vector<const char> string); |
+ |
+ Expression* NewCall(Expression* expression, |
+ ZoneList<Expression*>* arguments, |
+ int pos) { |
+ return new Call(expression, arguments, pos); |
+ } |
+ |
+ |
// Create a number literal. |
Literal* NewNumberLiteral(double value); |
@@ -639,6 +756,24 @@ class Parser { |
Expression* NewThrowError(Handle<String> constructor, |
Handle<String> type, |
Vector< Handle<Object> > arguments); |
+ |
+ ZoneList<Handle<String> > symbol_cache_; |
+ |
+ Handle<Script> script_; |
+ Scanner scanner_; |
+ |
+ Scope* top_scope_; |
+ int with_nesting_level_; |
+ |
+ TemporaryScope* temp_scope_; |
+ Mode mode_; |
+ |
+ Target* target_stack_; // for break, continue statements |
+ bool allow_natives_syntax_; |
+ v8::Extension* extension_; |
+ bool is_pre_parsing_; |
+ ScriptDataImpl* pre_data_; |
+ FuncNameInferrer* fni_; |
}; |
@@ -673,6 +808,9 @@ class CompileTimeValue: public AllStatic { |
}; |
+// ---------------------------------------------------------------------------- |
+// JSON PARSING |
+ |
// JSON is a subset of JavaScript, as specified in, e.g., the ECMAScript 5 |
// specification section 15.12.1 (and appendix A.8). |
// The grammar is given section 15.12.1.2 (and appendix A.8.2). |