| Index: src/parser.cc
|
| ===================================================================
|
| --- src/parser.cc (revision 5457)
|
| +++ src/parser.cc (working copy)
|
| @@ -996,21 +996,23 @@
|
| int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
|
| if (id == 0) {
|
| // Put (symbol_id_ + 1) into entry and increment it.
|
| - symbol_id_++;
|
| - entry->value = reinterpret_cast<void*>(symbol_id_);
|
| + id = ++symbol_id_;
|
| + entry->value = reinterpret_cast<void*>(id);
|
| Vector<Vector<const char> > symbol = symbol_entries_.AddBlock(1, literal);
|
| entry->key = &symbol[0];
|
| - } else {
|
| - // Log a reuse of an earlier seen symbol.
|
| - symbol_store_.Add(start);
|
| - symbol_store_.Add(id - 1);
|
| }
|
| + symbol_store_.Add(id - 1);
|
| }
|
|
|
| virtual Vector<unsigned> ExtractData() {
|
| int function_size = function_store_.size();
|
| + // Add terminator to symbols, then pad to unsigned size.
|
| int symbol_size = symbol_store_.size();
|
| - int total_size = ScriptDataImpl::kHeaderSize + function_size + symbol_size;
|
| + int padding = sizeof(unsigned) - (symbol_size % sizeof(unsigned));
|
| + symbol_store_.AddBlock(padding, ScriptDataImpl::kNumberTerminator);
|
| + symbol_size += padding;
|
| + int total_size = ScriptDataImpl::kHeaderSize + function_size
|
| + + (symbol_size / sizeof(unsigned));
|
| Vector<unsigned> data = Vector<unsigned>::New(total_size);
|
| preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size;
|
| preamble_[ScriptDataImpl::kSymbolCountOffset] = symbol_id_;
|
| @@ -1020,8 +1022,9 @@
|
| function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize,
|
| symbol_start));
|
| }
|
| - if (symbol_size > 0) {
|
| - symbol_store_.WriteTo(data.SubVector(symbol_start, total_size));
|
| + if (!has_error()) {
|
| + symbol_store_.WriteTo(
|
| + Vector<byte>::cast(data.SubVector(symbol_start, total_size)));
|
| }
|
| return data;
|
| }
|
| @@ -1029,12 +1032,7 @@
|
| virtual int symbol_position() { return symbol_store_.size(); }
|
| virtual int symbol_ids() { return symbol_id_; }
|
| private:
|
| - Collector<unsigned> symbol_store_;
|
| - Collector<Vector<const char> > symbol_entries_;
|
| - HashMap symbol_table_;
|
| - int symbol_id_;
|
| -
|
| - static int vector_hash(Vector<const char> string) {
|
| + static int vector_hash(Vector<const char> string) {
|
| int hash = 0;
|
| for (int i = 0; i < string.length(); i++) {
|
| int c = string[i];
|
| @@ -1052,6 +1050,14 @@
|
| 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_;
|
| };
|
|
|
|
|
| @@ -1076,18 +1082,11 @@
|
| }
|
|
|
|
|
| -int ScriptDataImpl::GetSymbolIdentifier(int start) {
|
| - int next = symbol_index_ + 2;
|
| - if (next <= store_.length()
|
| - && static_cast<int>(store_[symbol_index_]) == start) {
|
| - symbol_index_ = next;
|
| - return store_[next - 1];
|
| - }
|
| - return symbol_id_++;
|
| +int ScriptDataImpl::GetSymbolIdentifier() {
|
| + return ReadNumber(&symbol_data_);
|
| }
|
|
|
|
|
| -
|
| bool ScriptDataImpl::SanityCheck() {
|
| // Check that the header data is valid and doesn't specify
|
| // point to positions outside the store.
|
| @@ -1118,7 +1117,7 @@
|
| int symbol_count =
|
| static_cast<int>(store_[ScriptDataImpl::kSymbolCountOffset]);
|
| if (symbol_count < 0) return false;
|
| - // Check that the total size has room both function entries.
|
| + // Check that the total size has room for header and function entries.
|
| int minimum_size =
|
| ScriptDataImpl::kHeaderSize + functions_size;
|
| if (store_.length() < minimum_size) return false;
|
| @@ -1158,6 +1157,22 @@
|
| }
|
|
|
|
|
| +void CompleteParserRecorder::WriteNumber(int number) {
|
| + ASSERT(number >= 0);
|
| +
|
| + int mask = (1 << 28) - 1;
|
| + for (int i = 28; i > 0; i -= 7) {
|
| + if (number > mask) {
|
| + symbol_store_.Add(static_cast<byte>(number >> i) | 0x80u);
|
| + number &= mask;
|
| + }
|
| + mask >>= 7;
|
| + }
|
| + symbol_store_.Add(static_cast<byte>(number));
|
| +}
|
| +
|
| +
|
| +
|
| const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
|
| int length = start[0];
|
| char* result = NewArray<char>(length + 1);
|
| @@ -1206,7 +1221,8 @@
|
| Vector<const char*> ScriptDataImpl::BuildArgs() {
|
| int arg_count = Read(kMessageArgCountPos);
|
| const char** array = NewArray<const char*>(arg_count);
|
| - // Position after the string starting at position 3.
|
| + // Position after text found by skipping past length field and
|
| + // length field content words.
|
| int pos = kMessageTextPos + 1 + Read(kMessageTextPos);
|
| for (int i = 0; i < arg_count; i++) {
|
| int count = 0;
|
| @@ -1287,7 +1303,8 @@
|
| public:
|
| CompletePreParser(Handle<Script> script, bool allow_natives_syntax,
|
| v8::Extension* extension)
|
| - : PreParser(script, allow_natives_syntax, extension, &recorder_) { }
|
| + : PreParser(script, allow_natives_syntax, extension, &recorder_),
|
| + recorder_() { }
|
| virtual PartialParserRecorder* recorder() { return &recorder_; }
|
| private:
|
| CompleteParserRecorder recorder_;
|
| @@ -1298,7 +1315,8 @@
|
| public:
|
| PartialPreParser(Handle<Script> script, bool allow_natives_syntax,
|
| v8::Extension* extension)
|
| - : PreParser(script, allow_natives_syntax, extension, &recorder_) { }
|
| + : PreParser(script, allow_natives_syntax, extension, &recorder_),
|
| + recorder_() { }
|
| virtual PartialParserRecorder* recorder() { return &recorder_; }
|
| private:
|
| PartialParserRecorder recorder_;
|
| @@ -1639,17 +1657,12 @@
|
|
|
|
|
| Handle<String> Parser::GetSymbol(bool* ok) {
|
| + log()->LogSymbol(scanner_.location().beg_pos, scanner_.literal());
|
| + int symbol_id = -1;
|
| if (pre_data() != NULL) {
|
| - int symbol_id =
|
| - pre_data()->GetSymbolIdentifier(scanner_.location().beg_pos);
|
| - if (symbol_id < 0) {
|
| - ReportInvalidPreparseData(Factory::empty_symbol(), ok);
|
| - return Handle<String>::null();
|
| - }
|
| - return factory()->LookupSymbol(symbol_id, scanner_.literal());
|
| + symbol_id = pre_data()->GetSymbolIdentifier();
|
| }
|
| - log()->LogSymbol(scanner_.location().beg_pos, scanner_.literal());
|
| - return factory()->LookupSymbol(-1, scanner_.literal());
|
| + return factory()->LookupSymbol(symbol_id, scanner_.literal());
|
| }
|
|
|
|
|
| @@ -4176,8 +4189,7 @@
|
| Counters::total_preparse_skipped.Increment(end_pos - function_block_pos);
|
| scanner_.SeekForward(end_pos);
|
| pre_data()->Skip(entry.predata_function_skip(),
|
| - entry.predata_symbol_skip(),
|
| - entry.symbol_id_skip());
|
| + entry.predata_symbol_skip());
|
| materialized_literal_count = entry.literal_count();
|
| expected_property_count = entry.property_count();
|
| only_simple_this_property_assignments = false;
|
| @@ -4191,7 +4203,6 @@
|
| FunctionEntry entry = log()->LogFunction(function_block_pos);
|
| int predata_function_position_before = log()->function_position();
|
| int predata_symbol_position_before = log()->symbol_position();
|
| - int symbol_ids_before = log()->symbol_ids();
|
| ParseSourceElements(&body, Token::RBRACE, CHECK_OK);
|
| materialized_literal_count = temp_scope.materialized_literal_count();
|
| expected_property_count = temp_scope.expected_property_count();
|
| @@ -4209,8 +4220,6 @@
|
| log()->function_position() - predata_function_position_before);
|
| entry.set_predata_symbol_skip(
|
| log()->symbol_position() - predata_symbol_position_before);
|
| - entry.set_symbol_id_skip(
|
| - log()->symbol_ids() - symbol_ids_before);
|
| }
|
| }
|
|
|
| @@ -4243,58 +4252,43 @@
|
|
|
| Expect(Token::MOD, CHECK_OK);
|
| Handle<String> name = ParseIdentifier(CHECK_OK);
|
| - Runtime::Function* function =
|
| - Runtime::FunctionForName(scanner_.literal());
|
| ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
|
| - if (function == NULL && extension_ != NULL) {
|
| + if (is_pre_parsing_) return NULL;
|
| +
|
| + if (extension_ != NULL) {
|
| // The extension structures are only accessible while parsing the
|
| // very first time not when reparsing because of lazy compilation.
|
| top_scope_->ForceEagerCompilation();
|
| }
|
|
|
| - // Check for built-in macros.
|
| - if (!is_pre_parsing_) {
|
| - if (function == Runtime::FunctionForId(Runtime::kIS_VAR)) {
|
| - // %IS_VAR(x)
|
| - // evaluates to x if x is a variable,
|
| - // leads to a parse error otherwise
|
| - if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
|
| - return args->at(0);
|
| - }
|
| - *ok = false;
|
| - // Check here for other macros.
|
| - // } else if (function == Runtime::FunctionForId(Runtime::kIS_VAR)) {
|
| - // ...
|
| - }
|
| + Runtime::Function* function = Runtime::FunctionForSymbol(name);
|
|
|
| - if (!*ok) {
|
| - // We found a macro but it failed.
|
| + // Check for built-in IS_VAR macro.
|
| + if (function != NULL &&
|
| + function->intrinsic_type == Runtime::RUNTIME &&
|
| + function->function_id == Runtime::kIS_VAR) {
|
| + // %IS_VAR(x) evaluates to x if x is a variable,
|
| + // leads to a parse error otherwise. Could be implemented as an
|
| + // inline function %_IS_VAR(x) to eliminate this special case.
|
| + if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
|
| + return args->at(0);
|
| + } else {
|
| ReportMessage("unable_to_parse", Vector<const char*>::empty());
|
| + *ok = false;
|
| return NULL;
|
| }
|
| }
|
|
|
| - // Check that the expected number arguments are passed to runtime functions.
|
| - if (!is_pre_parsing_) {
|
| - if (function != NULL
|
| - && function->nargs != -1
|
| - && function->nargs != args->length()) {
|
| - ReportMessage("illegal_access", Vector<const char*>::empty());
|
| - *ok = false;
|
| - return NULL;
|
| - } else if (function == NULL && !name.is_null()) {
|
| - // If this is not a runtime function implemented in C++ it might be an
|
| - // inlined runtime function.
|
| - int argc = CodeGenerator::InlineRuntimeCallArgumentsCount(name);
|
| - if (argc != -1 && argc != args->length()) {
|
| - ReportMessage("illegal_access", Vector<const char*>::empty());
|
| - *ok = false;
|
| - return NULL;
|
| - }
|
| - }
|
| + // Check that the expected number of arguments are being passed.
|
| + if (function != NULL &&
|
| + function->nargs != -1 &&
|
| + function->nargs != args->length()) {
|
| + ReportMessage("illegal_access", Vector<const char*>::empty());
|
| + *ok = false;
|
| + return NULL;
|
| }
|
|
|
| - // Otherwise we have a valid runtime call.
|
| + // We have a valid intrinsics call or a call to a builtin.
|
| return NEW(CallRuntime(name, function, args));
|
| }
|
|
|
| @@ -5497,6 +5491,47 @@
|
| }
|
|
|
|
|
| +void ScriptDataImpl::Initialize() {
|
| + if (store_.length() >= kHeaderSize) {
|
| + int symbol_data_offset = kHeaderSize + store_[kFunctionsSizeOffset];
|
| + if (store_.length() > symbol_data_offset) {
|
| + symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
|
| + } else {
|
| + // Partial preparse causes no symbol information.
|
| + symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
|
| + }
|
| + symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
|
| + }
|
| +}
|
| +
|
| +
|
| +int ScriptDataImpl::ReadNumber(byte** source) {
|
| + // Reads a number from symbol_data_ in base 128. The most significant
|
| + // bit marks that there are more digits.
|
| + // If the first byte is 0x80 (kNumberTerminator), it would normally
|
| + // represent a leading zero. Since that is useless, and therefore won't
|
| + // appear as the first digit of any actual value, it is used to
|
| + // mark the end of the input stream.
|
| + byte* data = *source;
|
| + if (data >= symbol_data_end_) return -1;
|
| + byte input = *data;
|
| + if (input == kNumberTerminator) {
|
| + // End of stream marker.
|
| + return -1;
|
| + }
|
| + int result = input & 0x7f;
|
| + data++;
|
| + while ((input & 0x80u) != 0) {
|
| + if (data >= symbol_data_end_) return -1;
|
| + input = *data;
|
| + result = (result << 7) | (input & 0x7f);
|
| + data++;
|
| + }
|
| + *source = data;
|
| + return result;
|
| +}
|
| +
|
| +
|
| ScriptDataImpl* PreParse(Handle<String> source,
|
| unibrow::CharacterStream* stream,
|
| v8::Extension* extension) {
|
|
|