OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 result = scanner()->AllocateInternalizedString(isolate_); | 217 result = scanner()->AllocateInternalizedString(isolate_); |
218 ASSERT(!result.is_null()); | 218 ASSERT(!result.is_null()); |
219 symbol_cache_.at(symbol_id) = result; | 219 symbol_cache_.at(symbol_id) = result; |
220 return result; | 220 return result; |
221 } | 221 } |
222 isolate()->counters()->total_preparse_symbols_skipped()->Increment(); | 222 isolate()->counters()->total_preparse_symbols_skipped()->Increment(); |
223 return result; | 223 return result; |
224 } | 224 } |
225 | 225 |
226 | 226 |
227 FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) { | 227 ScriptData* ScriptData::New(const char* data, int length) { |
| 228 // The length is obviously invalid. |
| 229 if (length % sizeof(unsigned) != 0) { |
| 230 return new ScriptData(); |
| 231 } |
| 232 |
| 233 int deserialized_data_length = length / sizeof(unsigned); |
| 234 unsigned* deserialized_data; |
| 235 ScriptData* script_data = new ScriptData(); |
| 236 script_data->owns_store_ = |
| 237 reinterpret_cast<intptr_t>(data) % sizeof(unsigned) != 0; |
| 238 if (script_data->owns_store_) { |
| 239 // Copy the data to align it. |
| 240 deserialized_data = i::NewArray<unsigned>(deserialized_data_length); |
| 241 i::CopyBytes(reinterpret_cast<char*>(deserialized_data), |
| 242 data, static_cast<size_t>(length)); |
| 243 } else { |
| 244 // If aligned, don't create a copy of the data. |
| 245 deserialized_data = reinterpret_cast<unsigned*>(const_cast<char*>(data)); |
| 246 } |
| 247 script_data->store_ = |
| 248 Vector<unsigned>(deserialized_data, deserialized_data_length); |
| 249 return script_data; |
| 250 } |
| 251 |
| 252 |
| 253 FunctionEntry ScriptData::GetFunctionEntry(int start) { |
228 // The current pre-data entry must be a FunctionEntry with the given | 254 // The current pre-data entry must be a FunctionEntry with the given |
229 // start position. | 255 // start position. |
230 if ((function_index_ + FunctionEntry::kSize <= store_.length()) | 256 if ((function_index_ + FunctionEntry::kSize <= store_.length()) |
231 && (static_cast<int>(store_[function_index_]) == start)) { | 257 && (static_cast<int>(store_[function_index_]) == start)) { |
232 int index = function_index_; | 258 int index = function_index_; |
233 function_index_ += FunctionEntry::kSize; | 259 function_index_ += FunctionEntry::kSize; |
234 return FunctionEntry(store_.SubVector(index, | 260 return FunctionEntry(store_.SubVector(index, |
235 index + FunctionEntry::kSize)); | 261 index + FunctionEntry::kSize)); |
236 } | 262 } |
237 return FunctionEntry(); | 263 return FunctionEntry(); |
238 } | 264 } |
239 | 265 |
240 | 266 |
241 int ScriptDataImpl::GetSymbolIdentifier() { | 267 int ScriptData::GetSymbolIdentifier() { |
242 return ReadNumber(&symbol_data_); | 268 return ReadNumber(&symbol_data_); |
243 } | 269 } |
244 | 270 |
245 | 271 |
246 bool ScriptDataImpl::SanityCheck() { | 272 bool ScriptData::SanityCheck() { |
247 // Check that the header data is valid and doesn't specify | 273 // Check that the header data is valid and doesn't specify |
248 // point to positions outside the store. | 274 // point to positions outside the store. |
249 if (store_.length() < PreparseDataConstants::kHeaderSize) return false; | 275 if (store_.length() < PreparseDataConstants::kHeaderSize) return false; |
250 if (magic() != PreparseDataConstants::kMagicNumber) return false; | 276 if (magic() != PreparseDataConstants::kMagicNumber) return false; |
251 if (version() != PreparseDataConstants::kCurrentVersion) return false; | 277 if (version() != PreparseDataConstants::kCurrentVersion) return false; |
252 if (has_error()) { | 278 if (has_error()) { |
253 // Extra sane sanity check for error message encoding. | 279 // Extra sane sanity check for error message encoding. |
254 if (store_.length() <= PreparseDataConstants::kHeaderSize | 280 if (store_.length() <= PreparseDataConstants::kHeaderSize |
255 + PreparseDataConstants::kMessageTextPos) { | 281 + PreparseDataConstants::kMessageTextPos) { |
256 return false; | 282 return false; |
(...skipping 28 matching lines...) Expand all Loading... |
285 if (symbol_count < 0) return false; | 311 if (symbol_count < 0) return false; |
286 // Check that the total size has room for header and function entries. | 312 // Check that the total size has room for header and function entries. |
287 int minimum_size = | 313 int minimum_size = |
288 PreparseDataConstants::kHeaderSize + functions_size; | 314 PreparseDataConstants::kHeaderSize + functions_size; |
289 if (store_.length() < minimum_size) return false; | 315 if (store_.length() < minimum_size) return false; |
290 return true; | 316 return true; |
291 } | 317 } |
292 | 318 |
293 | 319 |
294 | 320 |
295 const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) { | 321 const char* ScriptData::ReadString(unsigned* start, int* chars) { |
296 int length = start[0]; | 322 int length = start[0]; |
297 char* result = NewArray<char>(length + 1); | 323 char* result = NewArray<char>(length + 1); |
298 for (int i = 0; i < length; i++) { | 324 for (int i = 0; i < length; i++) { |
299 result[i] = start[i + 1]; | 325 result[i] = start[i + 1]; |
300 } | 326 } |
301 result[length] = '\0'; | 327 result[length] = '\0'; |
302 if (chars != NULL) *chars = length; | 328 if (chars != NULL) *chars = length; |
303 return result; | 329 return result; |
304 } | 330 } |
305 | 331 |
306 | 332 |
307 Scanner::Location ScriptDataImpl::MessageLocation() const { | 333 Scanner::Location ScriptData::MessageLocation() const { |
308 int beg_pos = Read(PreparseDataConstants::kMessageStartPos); | 334 int beg_pos = Read(PreparseDataConstants::kMessageStartPos); |
309 int end_pos = Read(PreparseDataConstants::kMessageEndPos); | 335 int end_pos = Read(PreparseDataConstants::kMessageEndPos); |
310 return Scanner::Location(beg_pos, end_pos); | 336 return Scanner::Location(beg_pos, end_pos); |
311 } | 337 } |
312 | 338 |
313 | 339 |
314 bool ScriptDataImpl::IsReferenceError() const { | 340 bool ScriptData::IsReferenceError() const { |
315 return Read(PreparseDataConstants::kIsReferenceErrorPos); | 341 return Read(PreparseDataConstants::kIsReferenceErrorPos); |
316 } | 342 } |
317 | 343 |
318 | 344 |
319 const char* ScriptDataImpl::BuildMessage() const { | 345 const char* ScriptData::BuildMessage() const { |
320 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos); | 346 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos); |
321 return ReadString(start, NULL); | 347 return ReadString(start, NULL); |
322 } | 348 } |
323 | 349 |
324 | 350 |
325 Vector<const char*> ScriptDataImpl::BuildArgs() const { | 351 Vector<const char*> ScriptData::BuildArgs() const { |
326 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos); | 352 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos); |
327 const char** array = NewArray<const char*>(arg_count); | 353 const char** array = NewArray<const char*>(arg_count); |
328 // Position after text found by skipping past length field and | 354 // Position after text found by skipping past length field and |
329 // length field content words. | 355 // length field content words. |
330 int pos = PreparseDataConstants::kMessageTextPos + 1 | 356 int pos = PreparseDataConstants::kMessageTextPos + 1 |
331 + Read(PreparseDataConstants::kMessageTextPos); | 357 + Read(PreparseDataConstants::kMessageTextPos); |
332 for (int i = 0; i < arg_count; i++) { | 358 for (int i = 0; i < arg_count; i++) { |
333 int count = 0; | 359 int count = 0; |
334 array[i] = ReadString(ReadAddress(pos), &count); | 360 array[i] = ReadString(ReadAddress(pos), &count); |
335 pos += count + 1; | 361 pos += count + 1; |
336 } | 362 } |
337 return Vector<const char*>(array, arg_count); | 363 return Vector<const char*>(array, arg_count); |
338 } | 364 } |
339 | 365 |
340 | 366 |
341 unsigned ScriptDataImpl::Read(int position) const { | 367 unsigned ScriptData::Read(int position) const { |
342 return store_[PreparseDataConstants::kHeaderSize + position]; | 368 return store_[PreparseDataConstants::kHeaderSize + position]; |
343 } | 369 } |
344 | 370 |
345 | 371 |
346 unsigned* ScriptDataImpl::ReadAddress(int position) const { | 372 unsigned* ScriptData::ReadAddress(int position) const { |
347 return &store_[PreparseDataConstants::kHeaderSize + position]; | 373 return &store_[PreparseDataConstants::kHeaderSize + position]; |
348 } | 374 } |
349 | 375 |
350 | 376 |
351 Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) { | 377 Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) { |
352 Scope* result = new(zone()) Scope(parent, scope_type, zone()); | 378 Scope* result = new(zone()) Scope(parent, scope_type, zone()); |
353 result->Initialize(); | 379 result->Initialize(); |
354 return result; | 380 return result; |
355 } | 381 } |
356 | 382 |
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
883 String* name = String::cast(info()->script()->name()); | 909 String* name = String::cast(info()->script()->name()); |
884 SmartArrayPointer<char> name_chars = name->ToCString(); | 910 SmartArrayPointer<char> name_chars = name->ToCString(); |
885 PrintF("[parsing script: %s", name_chars.get()); | 911 PrintF("[parsing script: %s", name_chars.get()); |
886 } else { | 912 } else { |
887 PrintF("[parsing script"); | 913 PrintF("[parsing script"); |
888 } | 914 } |
889 PrintF(" - took %0.3f ms]\n", ms); | 915 PrintF(" - took %0.3f ms]\n", ms); |
890 } | 916 } |
891 if (cached_data_mode_ == PRODUCE_CACHED_DATA) { | 917 if (cached_data_mode_ == PRODUCE_CACHED_DATA) { |
892 Vector<unsigned> store = recorder.ExtractData(); | 918 Vector<unsigned> store = recorder.ExtractData(); |
893 *cached_data_ = new ScriptDataImpl(store); | 919 *cached_data_ = new ScriptData(store); |
894 log_ = NULL; | 920 log_ = NULL; |
895 } | 921 } |
896 return result; | 922 return result; |
897 } | 923 } |
898 | 924 |
899 | 925 |
900 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, | 926 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, |
901 Handle<String> source) { | 927 Handle<String> source) { |
902 ASSERT(scope_ == NULL); | 928 ASSERT(scope_ == NULL); |
903 ASSERT(target_stack_ == NULL); | 929 ASSERT(target_stack_ == NULL); |
(...skipping 3626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4530 ranges->Add(CharacterRange::Everything(), zone()); | 4556 ranges->Add(CharacterRange::Everything(), zone()); |
4531 is_negated = !is_negated; | 4557 is_negated = !is_negated; |
4532 } | 4558 } |
4533 return new(zone()) RegExpCharacterClass(ranges, is_negated); | 4559 return new(zone()) RegExpCharacterClass(ranges, is_negated); |
4534 } | 4560 } |
4535 | 4561 |
4536 | 4562 |
4537 // ---------------------------------------------------------------------------- | 4563 // ---------------------------------------------------------------------------- |
4538 // The Parser interface. | 4564 // The Parser interface. |
4539 | 4565 |
4540 ScriptDataImpl::~ScriptDataImpl() { | 4566 ScriptData::~ScriptData() { |
4541 if (owns_store_) store_.Dispose(); | 4567 if (owns_store_) store_.Dispose(); |
4542 } | 4568 } |
4543 | 4569 |
4544 | 4570 |
4545 int ScriptDataImpl::Length() { | 4571 int ScriptData::Length() { |
4546 return store_.length() * sizeof(unsigned); | 4572 return store_.length() * sizeof(unsigned); |
4547 } | 4573 } |
4548 | 4574 |
4549 | 4575 |
4550 const char* ScriptDataImpl::Data() { | 4576 const char* ScriptData::Data() { |
4551 return reinterpret_cast<const char*>(store_.start()); | 4577 return reinterpret_cast<const char*>(store_.start()); |
4552 } | 4578 } |
4553 | 4579 |
4554 | 4580 |
4555 bool ScriptDataImpl::HasError() { | 4581 bool ScriptData::HasError() { |
4556 return has_error(); | 4582 return has_error(); |
4557 } | 4583 } |
4558 | 4584 |
4559 | 4585 |
4560 void ScriptDataImpl::Initialize() { | 4586 void ScriptData::Initialize() { |
4561 // Prepares state for use. | 4587 // Prepares state for use. |
4562 if (store_.length() >= PreparseDataConstants::kHeaderSize) { | 4588 if (store_.length() >= PreparseDataConstants::kHeaderSize) { |
4563 function_index_ = PreparseDataConstants::kHeaderSize; | 4589 function_index_ = PreparseDataConstants::kHeaderSize; |
4564 int symbol_data_offset = PreparseDataConstants::kHeaderSize | 4590 int symbol_data_offset = PreparseDataConstants::kHeaderSize |
4565 + store_[PreparseDataConstants::kFunctionsSizeOffset]; | 4591 + store_[PreparseDataConstants::kFunctionsSizeOffset]; |
4566 if (store_.length() > symbol_data_offset) { | 4592 if (store_.length() > symbol_data_offset) { |
4567 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]); | 4593 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]); |
4568 } else { | 4594 } else { |
4569 // Partial preparse causes no symbol information. | 4595 // Partial preparse causes no symbol information. |
4570 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length()); | 4596 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length()); |
4571 } | 4597 } |
4572 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length()); | 4598 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length()); |
4573 } | 4599 } |
4574 } | 4600 } |
4575 | 4601 |
4576 | 4602 |
4577 int ScriptDataImpl::ReadNumber(byte** source) { | 4603 int ScriptData::ReadNumber(byte** source) { |
4578 // Reads a number from symbol_data_ in base 128. The most significant | 4604 // Reads a number from symbol_data_ in base 128. The most significant |
4579 // bit marks that there are more digits. | 4605 // bit marks that there are more digits. |
4580 // If the first byte is 0x80 (kNumberTerminator), it would normally | 4606 // If the first byte is 0x80 (kNumberTerminator), it would normally |
4581 // represent a leading zero. Since that is useless, and therefore won't | 4607 // represent a leading zero. Since that is useless, and therefore won't |
4582 // appear as the first digit of any actual value, it is used to | 4608 // appear as the first digit of any actual value, it is used to |
4583 // mark the end of the input stream. | 4609 // mark the end of the input stream. |
4584 byte* data = *source; | 4610 byte* data = *source; |
4585 if (data >= symbol_data_end_) return -1; | 4611 if (data >= symbol_data_end_) return -1; |
4586 byte input = *data; | 4612 byte input = *data; |
4587 if (input == PreparseDataConstants::kNumberTerminator) { | 4613 if (input == PreparseDataConstants::kNumberTerminator) { |
4588 // End of stream marker. | 4614 // End of stream marker. |
4589 return -1; | 4615 return -1; |
4590 } | 4616 } |
4591 int result = input & 0x7f; | 4617 int result = input & 0x7f; |
4592 data++; | 4618 data++; |
4593 while ((input & 0x80u) != 0) { | 4619 while ((input & 0x80u) != 0) { |
4594 if (data >= symbol_data_end_) return -1; | 4620 if (data >= symbol_data_end_) return -1; |
4595 input = *data; | 4621 input = *data; |
4596 result = (result << 7) | (input & 0x7f); | 4622 result = (result << 7) | (input & 0x7f); |
4597 data++; | 4623 data++; |
4598 } | 4624 } |
4599 *source = data; | 4625 *source = data; |
4600 return result; | 4626 return result; |
4601 } | 4627 } |
4602 | 4628 |
4603 | 4629 |
4604 // Create a Scanner for the preparser to use as input, and preparse the source. | |
4605 ScriptDataImpl* PreParserApi::PreParse(Isolate* isolate, | |
4606 Utf16CharacterStream* source) { | |
4607 CompleteParserRecorder recorder; | |
4608 HistogramTimerScope timer(isolate->counters()->pre_parse()); | |
4609 Scanner scanner(isolate->unicode_cache()); | |
4610 intptr_t stack_limit = isolate->stack_guard()->real_climit(); | |
4611 PreParser preparser(&scanner, &recorder, stack_limit); | |
4612 preparser.set_allow_lazy(true); | |
4613 preparser.set_allow_generators(FLAG_harmony_generators); | |
4614 preparser.set_allow_for_of(FLAG_harmony_iteration); | |
4615 preparser.set_allow_harmony_scoping(FLAG_harmony_scoping); | |
4616 preparser.set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); | |
4617 scanner.Initialize(source); | |
4618 PreParser::PreParseResult result = preparser.PreParseProgram(); | |
4619 if (result == PreParser::kPreParseStackOverflow) { | |
4620 isolate->StackOverflow(); | |
4621 return NULL; | |
4622 } | |
4623 | |
4624 // Extract the accumulated data from the recorder as a single | |
4625 // contiguous vector that we are responsible for disposing. | |
4626 Vector<unsigned> store = recorder.ExtractData(); | |
4627 return new ScriptDataImpl(store); | |
4628 } | |
4629 | |
4630 | |
4631 bool RegExpParser::ParseRegExp(FlatStringReader* input, | 4630 bool RegExpParser::ParseRegExp(FlatStringReader* input, |
4632 bool multiline, | 4631 bool multiline, |
4633 RegExpCompileData* result, | 4632 RegExpCompileData* result, |
4634 Zone* zone) { | 4633 Zone* zone) { |
4635 ASSERT(result != NULL); | 4634 ASSERT(result != NULL); |
4636 RegExpParser parser(input, &result->error, multiline, zone); | 4635 RegExpParser parser(input, &result->error, multiline, zone); |
4637 RegExpTree* tree = parser.ParsePattern(); | 4636 RegExpTree* tree = parser.ParsePattern(); |
4638 if (parser.failed()) { | 4637 if (parser.failed()) { |
4639 ASSERT(tree == NULL); | 4638 ASSERT(tree == NULL); |
4640 ASSERT(!result->error.is_null()); | 4639 ASSERT(!result->error.is_null()); |
(...skipping 17 matching lines...) Expand all Loading... |
4658 ASSERT(!info()->is_eval()); | 4657 ASSERT(!info()->is_eval()); |
4659 if (info()->shared_info()->is_function()) { | 4658 if (info()->shared_info()->is_function()) { |
4660 result = ParseLazy(); | 4659 result = ParseLazy(); |
4661 } else { | 4660 } else { |
4662 result = ParseProgram(); | 4661 result = ParseProgram(); |
4663 } | 4662 } |
4664 } else { | 4663 } else { |
4665 SetCachedData(info()->cached_data(), info()->cached_data_mode()); | 4664 SetCachedData(info()->cached_data(), info()->cached_data_mode()); |
4666 if (info()->cached_data_mode() == CONSUME_CACHED_DATA && | 4665 if (info()->cached_data_mode() == CONSUME_CACHED_DATA && |
4667 (*info()->cached_data())->has_error()) { | 4666 (*info()->cached_data())->has_error()) { |
4668 ScriptDataImpl* cached_data = *(info()->cached_data()); | 4667 ScriptData* cached_data = *(info()->cached_data()); |
4669 Scanner::Location loc = cached_data->MessageLocation(); | 4668 Scanner::Location loc = cached_data->MessageLocation(); |
4670 const char* message = cached_data->BuildMessage(); | 4669 const char* message = cached_data->BuildMessage(); |
4671 Vector<const char*> args = cached_data->BuildArgs(); | 4670 Vector<const char*> args = cached_data->BuildArgs(); |
4672 ParserTraits::ReportMessageAt(loc, message, args, | 4671 ParserTraits::ReportMessageAt(loc, message, args, |
4673 cached_data->IsReferenceError()); | 4672 cached_data->IsReferenceError()); |
4674 DeleteArray(message); | 4673 DeleteArray(message); |
4675 for (int i = 0; i < args.length(); i++) { | 4674 for (int i = 0; i < args.length(); i++) { |
4676 DeleteArray(args[i]); | 4675 DeleteArray(args[i]); |
4677 } | 4676 } |
4678 DeleteArray(args.start()); | 4677 DeleteArray(args.start()); |
4679 ASSERT(info()->isolate()->has_pending_exception()); | 4678 ASSERT(info()->isolate()->has_pending_exception()); |
4680 } else { | 4679 } else { |
4681 result = ParseProgram(); | 4680 result = ParseProgram(); |
4682 } | 4681 } |
4683 } | 4682 } |
4684 info()->SetFunction(result); | 4683 info()->SetFunction(result); |
4685 return (result != NULL); | 4684 return (result != NULL); |
4686 } | 4685 } |
4687 | 4686 |
4688 } } // namespace v8::internal | 4687 } } // namespace v8::internal |
OLD | NEW |