Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/ast.h" | 8 #include "src/ast.h" |
| 9 #include "src/base/platform/platform.h" | 9 #include "src/base/platform/platform.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 175 // Only call immediately after adding an atom or character! | 175 // Only call immediately after adding an atom or character! |
| 176 UNREACHABLE(); | 176 UNREACHABLE(); |
| 177 return; | 177 return; |
| 178 } | 178 } |
| 179 terms_.Add( | 179 terms_.Add( |
| 180 new(zone()) RegExpQuantifier(min, max, quantifier_type, atom), zone()); | 180 new(zone()) RegExpQuantifier(min, max, quantifier_type, atom), zone()); |
| 181 LAST(ADD_TERM); | 181 LAST(ADD_TERM); |
| 182 } | 182 } |
| 183 | 183 |
| 184 | 184 |
| 185 ScriptData* ScriptData::New(const char* data, int length, bool owns_store) { | 185 FunctionEntry ParseData::GetFunctionEntry(int start) { |
| 186 // The length is obviously invalid. | |
| 187 if (length % sizeof(unsigned) != 0) { | |
| 188 return NULL; | |
| 189 } | |
| 190 | |
| 191 int deserialized_data_length = length / sizeof(unsigned); | |
| 192 unsigned* deserialized_data; | |
| 193 owns_store = | |
| 194 owns_store || reinterpret_cast<intptr_t>(data) % sizeof(unsigned) != 0; | |
| 195 if (owns_store) { | |
| 196 // Copy the data to align it. | |
| 197 deserialized_data = i::NewArray<unsigned>(deserialized_data_length); | |
| 198 i::CopyBytes(reinterpret_cast<char*>(deserialized_data), | |
| 199 data, static_cast<size_t>(length)); | |
| 200 } else { | |
| 201 // If aligned, don't create a copy of the data. | |
| 202 deserialized_data = reinterpret_cast<unsigned*>(const_cast<char*>(data)); | |
| 203 } | |
| 204 return new ScriptData( | |
| 205 Vector<unsigned>(deserialized_data, deserialized_data_length), | |
| 206 owns_store); | |
| 207 } | |
| 208 | |
| 209 | |
| 210 FunctionEntry ScriptData::GetFunctionEntry(int start) { | |
| 211 // The current pre-data entry must be a FunctionEntry with the given | 186 // The current pre-data entry must be a FunctionEntry with the given |
| 212 // start position. | 187 // start position. |
| 213 if ((function_index_ + FunctionEntry::kSize <= store_.length()) | 188 if ((function_index_ + FunctionEntry::kSize <= Length()) && |
| 214 && (static_cast<int>(store_[function_index_]) == start)) { | 189 (static_cast<int>(Data()[function_index_]) == start)) { |
| 215 int index = function_index_; | 190 int index = function_index_; |
| 216 function_index_ += FunctionEntry::kSize; | 191 function_index_ += FunctionEntry::kSize; |
| 217 return FunctionEntry(store_.SubVector(index, | 192 Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize); |
| 218 index + FunctionEntry::kSize)); | 193 return FunctionEntry(subvector); |
| 219 } | 194 } |
| 220 return FunctionEntry(); | 195 return FunctionEntry(); |
| 221 } | 196 } |
| 222 | 197 |
| 223 | 198 |
| 224 int ScriptData::GetSymbolIdentifier() { | 199 int ParseData::GetSymbolIdentifier() { return ReadNumber(&symbol_data_); } |
| 225 return ReadNumber(&symbol_data_); | 200 |
| 201 | |
| 202 int ParseData::FunctionCount() { | |
| 203 int functions_size = FunctionsSize(); | |
| 204 if (functions_size < 0) return 0; | |
| 205 if (functions_size % FunctionEntry::kSize != 0) return 0; | |
| 206 return functions_size / FunctionEntry::kSize; | |
| 226 } | 207 } |
| 227 | 208 |
| 228 | 209 |
| 229 bool ScriptData::SanityCheck() { | 210 bool ParseData::Sanity() { |
| 230 // Check that the header data is valid and doesn't specify | 211 // Check that the header data is valid and doesn't specify |
| 231 // point to positions outside the store. | 212 // point to positions outside the store. |
| 232 if (store_.length() < PreparseDataConstants::kHeaderSize) return false; | 213 int data_length = Length(); |
| 233 if (magic() != PreparseDataConstants::kMagicNumber) return false; | 214 if (data_length < PreparseDataConstants::kHeaderSize) return false; |
| 234 if (version() != PreparseDataConstants::kCurrentVersion) return false; | 215 if (Magic() != PreparseDataConstants::kMagicNumber) return false; |
| 235 if (has_error()) { | 216 if (Version() != PreparseDataConstants::kCurrentVersion) return false; |
| 217 if (HasError()) { | |
|
marja
2014/07/09 14:42:30
Afaics we'll never have an error in normal operati
Yang
2014/07/10 08:28:46
Done.
But if that's the case, couldn't we just re
| |
| 236 // Extra sane sanity check for error message encoding. | 218 // Extra sane sanity check for error message encoding. |
| 237 if (store_.length() <= PreparseDataConstants::kHeaderSize | 219 if (data_length <= PreparseDataConstants::kHeaderSize + |
| 238 + PreparseDataConstants::kMessageTextPos) { | 220 PreparseDataConstants::kMessageTextPos) { |
| 239 return false; | 221 return false; |
| 240 } | 222 } |
| 241 if (Read(PreparseDataConstants::kMessageStartPos) > | 223 if (Read(PreparseDataConstants::kMessageStartPos) > |
| 242 Read(PreparseDataConstants::kMessageEndPos)) { | 224 Read(PreparseDataConstants::kMessageEndPos)) { |
| 243 return false; | 225 return false; |
| 244 } | 226 } |
| 245 unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos); | 227 unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos); |
| 246 int pos = PreparseDataConstants::kMessageTextPos; | 228 int pos = PreparseDataConstants::kMessageTextPos; |
| 247 for (unsigned int i = 0; i <= arg_count; i++) { | 229 for (unsigned int i = 0; i <= arg_count; i++) { |
| 248 if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) { | 230 if (data_length <= PreparseDataConstants::kHeaderSize + pos) { |
| 249 return false; | 231 return false; |
| 250 } | 232 } |
| 251 int length = static_cast<int>(Read(pos)); | 233 int length = static_cast<int>(Read(pos)); |
| 252 if (length < 0) return false; | 234 if (length < 0) return false; |
| 253 pos += 1 + length; | 235 pos += 1 + length; |
| 254 } | 236 } |
| 255 if (store_.length() < PreparseDataConstants::kHeaderSize + pos) { | 237 if (data_length < PreparseDataConstants::kHeaderSize + pos) { |
| 256 return false; | 238 return false; |
| 257 } | 239 } |
| 258 return true; | 240 return true; |
| 259 } | 241 } |
| 260 // Check that the space allocated for function entries is sane. | 242 // Check that the space allocated for function entries is sane. |
| 261 int functions_size = | 243 int functions_size = FunctionsSize(); |
| 262 static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]); | |
| 263 if (functions_size < 0) return false; | 244 if (functions_size < 0) return false; |
| 264 if (functions_size % FunctionEntry::kSize != 0) return false; | 245 if (functions_size % FunctionEntry::kSize != 0) return false; |
| 265 // Check that the total size has room for header and function entries. | 246 // Check that the total size has room for header and function entries. |
| 266 int minimum_size = | 247 int minimum_size = |
| 267 PreparseDataConstants::kHeaderSize + functions_size; | 248 PreparseDataConstants::kHeaderSize + functions_size; |
| 268 if (store_.length() < minimum_size) return false; | 249 if (data_length < minimum_size) return false; |
| 269 return true; | 250 return true; |
| 270 } | 251 } |
| 271 | 252 |
| 272 | 253 |
| 254 void ParseData::Initialize() { | |
| 255 // Prepares state for use. | |
| 256 int data_length = Length(); | |
| 257 if (data_length >= PreparseDataConstants::kHeaderSize) { | |
| 258 function_index_ = PreparseDataConstants::kHeaderSize; | |
| 259 int symbol_data_offset = | |
|
marja
2014/07/09 14:42:30
Omg, this is messier than I thought. We don't have
Yang
2014/07/10 08:28:46
Done.
| |
| 260 PreparseDataConstants::kHeaderSize + FunctionsSize(); | |
| 261 unsigned* data = Data(); | |
| 262 if (data_length > symbol_data_offset) { | |
| 263 symbol_data_ = reinterpret_cast<byte*>(data[symbol_data_offset]); | |
| 264 } else { | |
| 265 // Partial preparse causes no symbol information. | |
| 266 symbol_data_ = reinterpret_cast<byte*>(data + data_length); | |
| 267 } | |
|
vogelheim
2014/07/09 17:23:36
nitpick, and not your code, but... this duplicates
Yang
2014/07/10 08:28:45
All gone now anyways.
| |
| 268 symbol_data_end_ = reinterpret_cast<byte*>(data + data_length); | |
| 269 } | |
| 270 } | |
| 273 | 271 |
| 274 const char* ScriptData::ReadString(unsigned* start, int* chars) { | 272 |
| 275 int length = start[0]; | 273 int ParseData::ReadNumber(byte** source) { |
| 276 char* result = NewArray<char>(length + 1); | 274 // Reads a number from symbol_data_ in base 128. The most significant |
| 277 for (int i = 0; i < length; i++) { | 275 // bit marks that there are more digits. |
| 278 result[i] = start[i + 1]; | 276 // If the first byte is 0x80 (kNumberTerminator), it would normally |
| 277 // represent a leading zero. Since that is useless, and therefore won't | |
| 278 // appear as the first digit of any actual value, it is used to | |
| 279 // mark the end of the input stream. | |
| 280 byte* data = *source; | |
| 281 if (data >= symbol_data_end_) return -1; | |
| 282 byte input = *data; | |
| 283 if (input == PreparseDataConstants::kNumberTerminator) { | |
| 284 // End of stream marker. | |
| 285 return -1; | |
| 279 } | 286 } |
| 280 result[length] = '\0'; | 287 int result = input & 0x7f; |
| 281 if (chars != NULL) *chars = length; | 288 data++; |
| 289 while ((input & 0x80u) != 0) { | |
| 290 if (data >= symbol_data_end_) return -1; | |
| 291 input = *data; | |
| 292 result = (result << 7) | (input & 0x7f); | |
| 293 data++; | |
| 294 } | |
| 295 *source = data; | |
| 282 return result; | 296 return result; |
| 283 } | 297 } |
| 284 | 298 |
| 285 | 299 |
| 286 Scanner::Location ScriptData::MessageLocation() const { | 300 Scanner::Location ParseData::MessageLocation() const { |
| 287 int beg_pos = Read(PreparseDataConstants::kMessageStartPos); | 301 int beg_pos = Read(PreparseDataConstants::kMessageStartPos); |
| 288 int end_pos = Read(PreparseDataConstants::kMessageEndPos); | 302 int end_pos = Read(PreparseDataConstants::kMessageEndPos); |
| 289 return Scanner::Location(beg_pos, end_pos); | 303 return Scanner::Location(beg_pos, end_pos); |
| 290 } | 304 } |
| 291 | 305 |
| 292 | 306 |
| 293 bool ScriptData::IsReferenceError() const { | 307 bool ParseData::IsReferenceError() const { |
| 294 return Read(PreparseDataConstants::kIsReferenceErrorPos); | 308 return Read(PreparseDataConstants::kIsReferenceErrorPos); |
| 295 } | 309 } |
| 296 | 310 |
| 297 | 311 |
| 298 const char* ScriptData::BuildMessage() const { | 312 const char* ParseData::BuildMessage() { |
| 299 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos); | 313 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos); |
| 300 return ReadString(start, NULL); | 314 return ReadString(start, NULL); |
| 301 } | 315 } |
| 302 | 316 |
| 303 | 317 |
| 304 const char* ScriptData::BuildArg() const { | 318 const char* ParseData::BuildArg() { |
| 305 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos); | 319 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos); |
| 306 ASSERT(arg_count == 0 || arg_count == 1); | 320 ASSERT(arg_count == 0 || arg_count == 1); |
| 307 if (arg_count == 0) { | 321 if (arg_count == 0) { |
| 308 return NULL; | 322 return NULL; |
| 309 } | 323 } |
| 310 // Position after text found by skipping past length field and | 324 // Position after text found by skipping past length field and |
| 311 // length field content words. | 325 // length field content words. |
| 312 int pos = PreparseDataConstants::kMessageTextPos + 1 | 326 int pos = PreparseDataConstants::kMessageTextPos + 1 |
| 313 + Read(PreparseDataConstants::kMessageTextPos); | 327 + Read(PreparseDataConstants::kMessageTextPos); |
| 314 int count = 0; | 328 int count = 0; |
| 315 return ReadString(ReadAddress(pos), &count); | 329 return ReadString(ReadAddress(pos), &count); |
| 316 } | 330 } |
| 317 | 331 |
| 318 | 332 |
| 319 unsigned ScriptData::Read(int position) const { | 333 const char* ParseData::ReadString(unsigned* start, int* chars) { |
| 320 return store_[PreparseDataConstants::kHeaderSize + position]; | 334 int length = start[0]; |
| 335 char* result = NewArray<char>(length + 1); | |
| 336 for (int i = 0; i < length; i++) { | |
| 337 result[i] = start[i + 1]; | |
| 338 } | |
| 339 result[length] = '\0'; | |
| 340 if (chars != NULL) *chars = length; | |
| 341 return result; | |
| 321 } | 342 } |
| 322 | 343 |
| 323 | 344 |
| 324 unsigned* ScriptData::ReadAddress(int position) const { | 345 bool ParseData::HasError() const { |
| 325 return &store_[PreparseDataConstants::kHeaderSize + position]; | 346 return Data()[PreparseDataConstants::kHasErrorOffset]; |
| 347 } | |
| 348 | |
| 349 unsigned ParseData::Magic() const { | |
| 350 return Data()[PreparseDataConstants::kMagicOffset]; | |
| 351 } | |
| 352 | |
| 353 unsigned ParseData::Version() const { | |
| 354 return Data()[PreparseDataConstants::kVersionOffset]; | |
| 355 } | |
| 356 | |
| 357 int ParseData::FunctionsSize() const { | |
| 358 return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]); | |
| 359 } | |
| 360 | |
| 361 unsigned ParseData::Read(int position) const { | |
| 362 return Data()[PreparseDataConstants::kHeaderSize + position]; | |
| 363 } | |
| 364 | |
| 365 unsigned* ParseData::ReadAddress(int position) const { | |
| 366 return &(Data()[PreparseDataConstants::kHeaderSize + position]); | |
| 326 } | 367 } |
| 327 | 368 |
| 328 | 369 |
| 370 void Parser::SetCachedData() { | |
| 371 if (cached_data_mode() == NO_CACHED_DATA) { | |
| 372 cached_parse_data_ = NULL; | |
| 373 } else { | |
| 374 ASSERT(info_->cached_data() != NULL); | |
| 375 if (cached_data_mode() == CONSUME_CACHED_DATA) { | |
| 376 cached_parse_data_ = new ParseData(*info_->cached_data()); | |
| 377 } | |
| 378 } | |
| 379 } | |
| 380 | |
| 381 | |
| 329 Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) { | 382 Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) { |
| 330 ASSERT(ast_value_factory_); | 383 ASSERT(ast_value_factory_); |
| 331 Scope* result = | 384 Scope* result = |
| 332 new (zone()) Scope(parent, scope_type, ast_value_factory_, zone()); | 385 new (zone()) Scope(parent, scope_type, ast_value_factory_, zone()); |
| 333 result->Initialize(); | 386 result->Initialize(); |
| 334 return result; | 387 return result; |
| 335 } | 388 } |
| 336 | 389 |
| 337 | 390 |
| 338 // ---------------------------------------------------------------------------- | 391 // ---------------------------------------------------------------------------- |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 750 return parser_->ParseFunctionLiteral(name, function_name_location, | 803 return parser_->ParseFunctionLiteral(name, function_name_location, |
| 751 name_is_strict_reserved, is_generator, | 804 name_is_strict_reserved, is_generator, |
| 752 function_token_position, type, | 805 function_token_position, type, |
| 753 arity_restriction, ok); | 806 arity_restriction, ok); |
| 754 } | 807 } |
| 755 | 808 |
| 756 | 809 |
| 757 Parser::Parser(CompilationInfo* info) | 810 Parser::Parser(CompilationInfo* info) |
| 758 : ParserBase<ParserTraits>(&scanner_, | 811 : ParserBase<ParserTraits>(&scanner_, |
| 759 info->isolate()->stack_guard()->real_climit(), | 812 info->isolate()->stack_guard()->real_climit(), |
| 760 info->extension(), | 813 info->extension(), NULL, info->zone(), this), |
| 761 NULL, | |
| 762 info->zone(), | |
| 763 this), | |
| 764 isolate_(info->isolate()), | 814 isolate_(info->isolate()), |
| 765 script_(info->script()), | 815 script_(info->script()), |
| 766 scanner_(isolate_->unicode_cache()), | 816 scanner_(isolate_->unicode_cache()), |
| 767 reusable_preparser_(NULL), | 817 reusable_preparser_(NULL), |
| 768 original_scope_(NULL), | 818 original_scope_(NULL), |
| 769 target_stack_(NULL), | 819 target_stack_(NULL), |
| 770 cached_data_(NULL), | 820 cached_parse_data_(NULL), |
| 771 cached_data_mode_(NO_CACHED_DATA), | |
| 772 ast_value_factory_(NULL), | 821 ast_value_factory_(NULL), |
| 773 info_(info), | 822 info_(info), |
| 774 has_pending_error_(false), | 823 has_pending_error_(false), |
| 775 pending_error_message_(NULL), | 824 pending_error_message_(NULL), |
| 776 pending_error_arg_(NULL), | 825 pending_error_arg_(NULL), |
| 777 pending_error_char_arg_(NULL) { | 826 pending_error_char_arg_(NULL) { |
| 778 ASSERT(!script_.is_null()); | 827 ASSERT(!script_.is_null()); |
| 779 isolate_->set_ast_node_id(0); | 828 isolate_->set_ast_node_id(0); |
| 780 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping); | 829 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping); |
| 781 set_allow_modules(!info->is_native() && FLAG_harmony_modules); | 830 set_allow_modules(!info->is_native() && FLAG_harmony_modules); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 798 Handle<String> source(String::cast(script_->source())); | 847 Handle<String> source(String::cast(script_->source())); |
| 799 isolate()->counters()->total_parse_size()->Increment(source->length()); | 848 isolate()->counters()->total_parse_size()->Increment(source->length()); |
| 800 base::ElapsedTimer timer; | 849 base::ElapsedTimer timer; |
| 801 if (FLAG_trace_parse) { | 850 if (FLAG_trace_parse) { |
| 802 timer.Start(); | 851 timer.Start(); |
| 803 } | 852 } |
| 804 fni_ = new(zone()) FuncNameInferrer(ast_value_factory_, zone()); | 853 fni_ = new(zone()) FuncNameInferrer(ast_value_factory_, zone()); |
| 805 | 854 |
| 806 // Initialize parser state. | 855 // Initialize parser state. |
| 807 CompleteParserRecorder recorder; | 856 CompleteParserRecorder recorder; |
| 808 if (cached_data_mode_ == PRODUCE_CACHED_DATA) { | 857 if (cached_data_mode() == PRODUCE_CACHED_DATA) { |
| 809 log_ = &recorder; | 858 log_ = &recorder; |
| 810 } else if (cached_data_mode_ == CONSUME_CACHED_DATA) { | 859 } else if (cached_data_mode() == CONSUME_CACHED_DATA) { |
| 811 (*cached_data_)->Initialize(); | 860 cached_parse_data_->Initialize(); |
| 812 } | 861 } |
| 813 | 862 |
| 814 source = String::Flatten(source); | 863 source = String::Flatten(source); |
| 815 FunctionLiteral* result; | 864 FunctionLiteral* result; |
| 816 if (source->IsExternalTwoByteString()) { | 865 if (source->IsExternalTwoByteString()) { |
| 817 // Notice that the stream is destroyed at the end of the branch block. | 866 // Notice that the stream is destroyed at the end of the branch block. |
| 818 // The last line of the blocks can't be moved outside, even though they're | 867 // The last line of the blocks can't be moved outside, even though they're |
| 819 // identical calls. | 868 // identical calls. |
| 820 ExternalTwoByteStringUtf16CharacterStream stream( | 869 ExternalTwoByteStringUtf16CharacterStream stream( |
| 821 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); | 870 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 833 PrintF("[parsing eval"); | 882 PrintF("[parsing eval"); |
| 834 } else if (info()->script()->name()->IsString()) { | 883 } else if (info()->script()->name()->IsString()) { |
| 835 String* name = String::cast(info()->script()->name()); | 884 String* name = String::cast(info()->script()->name()); |
| 836 SmartArrayPointer<char> name_chars = name->ToCString(); | 885 SmartArrayPointer<char> name_chars = name->ToCString(); |
| 837 PrintF("[parsing script: %s", name_chars.get()); | 886 PrintF("[parsing script: %s", name_chars.get()); |
| 838 } else { | 887 } else { |
| 839 PrintF("[parsing script"); | 888 PrintF("[parsing script"); |
| 840 } | 889 } |
| 841 PrintF(" - took %0.3f ms]\n", ms); | 890 PrintF(" - took %0.3f ms]\n", ms); |
| 842 } | 891 } |
| 843 if (cached_data_mode_ == PRODUCE_CACHED_DATA) { | 892 if (cached_data_mode() == PRODUCE_CACHED_DATA) { |
| 844 if (result != NULL) { | 893 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); |
| 845 Vector<unsigned> store = recorder.ExtractData(); | |
| 846 *cached_data_ = new ScriptData(store); | |
| 847 } | |
| 848 log_ = NULL; | 894 log_ = NULL; |
| 849 } | 895 } |
| 850 return result; | 896 return result; |
| 851 } | 897 } |
| 852 | 898 |
| 853 | 899 |
| 854 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, | 900 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, |
| 855 Handle<String> source) { | 901 Handle<String> source) { |
| 856 ASSERT(scope_ == NULL); | 902 ASSERT(scope_ == NULL); |
| 857 ASSERT(target_stack_ == NULL); | 903 ASSERT(target_stack_ == NULL); |
| (...skipping 2428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3286 // DebuggerStatement :: | 3332 // DebuggerStatement :: |
| 3287 // 'debugger' ';' | 3333 // 'debugger' ';' |
| 3288 | 3334 |
| 3289 int pos = peek_position(); | 3335 int pos = peek_position(); |
| 3290 Expect(Token::DEBUGGER, CHECK_OK); | 3336 Expect(Token::DEBUGGER, CHECK_OK); |
| 3291 ExpectSemicolon(CHECK_OK); | 3337 ExpectSemicolon(CHECK_OK); |
| 3292 return factory()->NewDebuggerStatement(pos); | 3338 return factory()->NewDebuggerStatement(pos); |
| 3293 } | 3339 } |
| 3294 | 3340 |
| 3295 | 3341 |
| 3296 void Parser::ReportInvalidCachedData(const AstRawString* name, bool* ok) { | |
| 3297 ParserTraits::ReportMessage("invalid_cached_data_function", name); | |
| 3298 *ok = false; | |
| 3299 } | |
| 3300 | |
| 3301 | |
| 3302 bool CompileTimeValue::IsCompileTimeValue(Expression* expression) { | 3342 bool CompileTimeValue::IsCompileTimeValue(Expression* expression) { |
| 3303 if (expression->IsLiteral()) return true; | 3343 if (expression->IsLiteral()) return true; |
| 3304 MaterializedLiteral* lit = expression->AsMaterializedLiteral(); | 3344 MaterializedLiteral* lit = expression->AsMaterializedLiteral(); |
| 3305 return lit != NULL && lit->is_simple(); | 3345 return lit != NULL && lit->is_simple(); |
| 3306 } | 3346 } |
| 3307 | 3347 |
| 3308 | 3348 |
| 3309 Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate, | 3349 Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate, |
| 3310 Expression* expression) { | 3350 Expression* expression) { |
| 3311 Factory* factory = isolate->factory(); | 3351 Factory* factory = isolate->factory(); |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3608 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); | 3648 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); |
| 3609 return function_literal; | 3649 return function_literal; |
| 3610 } | 3650 } |
| 3611 | 3651 |
| 3612 | 3652 |
| 3613 void Parser::SkipLazyFunctionBody(const AstRawString* function_name, | 3653 void Parser::SkipLazyFunctionBody(const AstRawString* function_name, |
| 3614 int* materialized_literal_count, | 3654 int* materialized_literal_count, |
| 3615 int* expected_property_count, | 3655 int* expected_property_count, |
| 3616 bool* ok) { | 3656 bool* ok) { |
| 3617 int function_block_pos = position(); | 3657 int function_block_pos = position(); |
| 3618 if (cached_data_mode_ == CONSUME_CACHED_DATA) { | 3658 if (cached_data_mode() == CONSUME_CACHED_DATA) { |
| 3619 // If we have cached data, we use it to skip parsing the function body. The | 3659 // If we have cached data, we use it to skip parsing the function body. The |
| 3620 // data contains the information we need to construct the lazy function. | 3660 // data contains the information we need to construct the lazy function. |
| 3621 FunctionEntry entry = | 3661 FunctionEntry entry = |
| 3622 (*cached_data())->GetFunctionEntry(function_block_pos); | 3662 cached_parse_data_->GetFunctionEntry(function_block_pos); |
| 3623 if (entry.is_valid()) { | 3663 // Invalid cached data if checks fail. |
|
vogelheim
2014/07/09 17:23:36
I can't really parse the comment.
Yang
2014/07/10 08:28:45
Changed.
| |
| 3624 if (entry.end_pos() <= function_block_pos) { | 3664 CHECK(entry.is_valid()); |
| 3625 // End position greater than end of stream is safe, and hard to check. | 3665 // End position greater than end of stream is safe, and hard to check. |
| 3626 ReportInvalidCachedData(function_name, ok); | 3666 CHECK(entry.end_pos() > function_block_pos); |
| 3627 if (!*ok) { | 3667 scanner()->SeekForward(entry.end_pos() - 1); |
| 3628 return; | |
| 3629 } | |
| 3630 } | |
| 3631 scanner()->SeekForward(entry.end_pos() - 1); | |
| 3632 | 3668 |
| 3633 scope_->set_end_position(entry.end_pos()); | 3669 scope_->set_end_position(entry.end_pos()); |
| 3634 Expect(Token::RBRACE, ok); | 3670 Expect(Token::RBRACE, ok); |
| 3635 if (!*ok) { | 3671 if (!*ok) { |
| 3636 return; | |
| 3637 } | |
| 3638 isolate()->counters()->total_preparse_skipped()->Increment( | |
| 3639 scope_->end_position() - function_block_pos); | |
| 3640 *materialized_literal_count = entry.literal_count(); | |
| 3641 *expected_property_count = entry.property_count(); | |
| 3642 scope_->SetStrictMode(entry.strict_mode()); | |
| 3643 } else { | |
| 3644 // This case happens when we have preparse data but it doesn't contain an | |
| 3645 // entry for the function. Fail the compilation. | |
| 3646 ReportInvalidCachedData(function_name, ok); | |
| 3647 return; | 3672 return; |
| 3648 } | 3673 } |
| 3674 isolate()->counters()->total_preparse_skipped()->Increment( | |
| 3675 scope_->end_position() - function_block_pos); | |
| 3676 *materialized_literal_count = entry.literal_count(); | |
| 3677 *expected_property_count = entry.property_count(); | |
| 3678 scope_->SetStrictMode(entry.strict_mode()); | |
| 3649 } else { | 3679 } else { |
| 3650 // With no cached data, we partially parse the function, without building an | 3680 // With no cached data, we partially parse the function, without building an |
| 3651 // AST. This gathers the data needed to build a lazy function. | 3681 // AST. This gathers the data needed to build a lazy function. |
| 3652 SingletonLogger logger; | 3682 SingletonLogger logger; |
| 3653 PreParser::PreParseResult result = | 3683 PreParser::PreParseResult result = |
| 3654 ParseLazyFunctionBodyWithPreParser(&logger); | 3684 ParseLazyFunctionBodyWithPreParser(&logger); |
| 3655 if (result == PreParser::kPreParseStackOverflow) { | 3685 if (result == PreParser::kPreParseStackOverflow) { |
| 3656 // Propagate stack overflow. | 3686 // Propagate stack overflow. |
| 3657 set_stack_overflow(); | 3687 set_stack_overflow(); |
| 3658 *ok = false; | 3688 *ok = false; |
| 3659 return; | 3689 return; |
| 3660 } | 3690 } |
| 3661 if (logger.has_error()) { | 3691 if (logger.has_error()) { |
| 3662 ParserTraits::ReportMessageAt( | 3692 ParserTraits::ReportMessageAt( |
| 3663 Scanner::Location(logger.start(), logger.end()), | 3693 Scanner::Location(logger.start(), logger.end()), |
| 3664 logger.message(), logger.argument_opt(), logger.is_reference_error()); | 3694 logger.message(), logger.argument_opt(), logger.is_reference_error()); |
| 3665 *ok = false; | 3695 *ok = false; |
| 3666 return; | 3696 return; |
| 3667 } | 3697 } |
| 3668 scope_->set_end_position(logger.end()); | 3698 scope_->set_end_position(logger.end()); |
| 3669 Expect(Token::RBRACE, ok); | 3699 Expect(Token::RBRACE, ok); |
| 3670 if (!*ok) { | 3700 if (!*ok) { |
| 3671 return; | 3701 return; |
| 3672 } | 3702 } |
| 3673 isolate()->counters()->total_preparse_skipped()->Increment( | 3703 isolate()->counters()->total_preparse_skipped()->Increment( |
| 3674 scope_->end_position() - function_block_pos); | 3704 scope_->end_position() - function_block_pos); |
| 3675 *materialized_literal_count = logger.literals(); | 3705 *materialized_literal_count = logger.literals(); |
| 3676 *expected_property_count = logger.properties(); | 3706 *expected_property_count = logger.properties(); |
| 3677 scope_->SetStrictMode(logger.strict_mode()); | 3707 scope_->SetStrictMode(logger.strict_mode()); |
| 3678 if (cached_data_mode_ == PRODUCE_CACHED_DATA) { | 3708 if (cached_data_mode() == PRODUCE_CACHED_DATA) { |
| 3679 ASSERT(log_); | 3709 ASSERT(log_); |
| 3680 // Position right after terminal '}'. | 3710 // Position right after terminal '}'. |
| 3681 int body_end = scanner()->location().end_pos; | 3711 int body_end = scanner()->location().end_pos; |
| 3682 log_->LogFunction(function_block_pos, body_end, | 3712 log_->LogFunction(function_block_pos, body_end, |
| 3683 *materialized_literal_count, | 3713 *materialized_literal_count, |
| 3684 *expected_property_count, | 3714 *expected_property_count, |
| 3685 scope_->strict_mode()); | 3715 scope_->strict_mode()); |
| 3686 } | 3716 } |
| 3687 } | 3717 } |
| 3688 } | 3718 } |
| (...skipping 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4760 ranges->Add(CharacterRange::Everything(), zone()); | 4790 ranges->Add(CharacterRange::Everything(), zone()); |
| 4761 is_negated = !is_negated; | 4791 is_negated = !is_negated; |
| 4762 } | 4792 } |
| 4763 return new(zone()) RegExpCharacterClass(ranges, is_negated); | 4793 return new(zone()) RegExpCharacterClass(ranges, is_negated); |
| 4764 } | 4794 } |
| 4765 | 4795 |
| 4766 | 4796 |
| 4767 // ---------------------------------------------------------------------------- | 4797 // ---------------------------------------------------------------------------- |
| 4768 // The Parser interface. | 4798 // The Parser interface. |
| 4769 | 4799 |
| 4770 ScriptData::~ScriptData() { | |
| 4771 if (owns_store_) store_.Dispose(); | |
| 4772 } | |
| 4773 | |
| 4774 | |
| 4775 int ScriptData::Length() { | |
| 4776 return store_.length() * sizeof(unsigned); | |
| 4777 } | |
| 4778 | |
| 4779 | |
| 4780 const char* ScriptData::Data() { | |
| 4781 return reinterpret_cast<const char*>(store_.start()); | |
| 4782 } | |
| 4783 | |
| 4784 | |
| 4785 bool ScriptData::HasError() { | |
| 4786 return has_error(); | |
| 4787 } | |
| 4788 | |
| 4789 | |
| 4790 void ScriptData::Initialize() { | |
| 4791 // Prepares state for use. | |
| 4792 if (store_.length() >= PreparseDataConstants::kHeaderSize) { | |
| 4793 function_index_ = PreparseDataConstants::kHeaderSize; | |
| 4794 int symbol_data_offset = PreparseDataConstants::kHeaderSize | |
| 4795 + store_[PreparseDataConstants::kFunctionsSizeOffset]; | |
| 4796 if (store_.length() > symbol_data_offset) { | |
| 4797 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]); | |
| 4798 } else { | |
| 4799 // Partial preparse causes no symbol information. | |
| 4800 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length()); | |
| 4801 } | |
| 4802 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length()); | |
| 4803 } | |
| 4804 } | |
| 4805 | |
| 4806 | |
| 4807 int ScriptData::ReadNumber(byte** source) { | |
| 4808 // Reads a number from symbol_data_ in base 128. The most significant | |
| 4809 // bit marks that there are more digits. | |
| 4810 // If the first byte is 0x80 (kNumberTerminator), it would normally | |
| 4811 // represent a leading zero. Since that is useless, and therefore won't | |
| 4812 // appear as the first digit of any actual value, it is used to | |
| 4813 // mark the end of the input stream. | |
| 4814 byte* data = *source; | |
| 4815 if (data >= symbol_data_end_) return -1; | |
| 4816 byte input = *data; | |
| 4817 if (input == PreparseDataConstants::kNumberTerminator) { | |
| 4818 // End of stream marker. | |
| 4819 return -1; | |
| 4820 } | |
| 4821 int result = input & 0x7f; | |
| 4822 data++; | |
| 4823 while ((input & 0x80u) != 0) { | |
| 4824 if (data >= symbol_data_end_) return -1; | |
| 4825 input = *data; | |
| 4826 result = (result << 7) | (input & 0x7f); | |
| 4827 data++; | |
| 4828 } | |
| 4829 *source = data; | |
| 4830 return result; | |
| 4831 } | |
| 4832 | |
| 4833 | |
| 4834 bool RegExpParser::ParseRegExp(FlatStringReader* input, | 4800 bool RegExpParser::ParseRegExp(FlatStringReader* input, |
| 4835 bool multiline, | 4801 bool multiline, |
| 4836 RegExpCompileData* result, | 4802 RegExpCompileData* result, |
| 4837 Zone* zone) { | 4803 Zone* zone) { |
| 4838 ASSERT(result != NULL); | 4804 ASSERT(result != NULL); |
| 4839 RegExpParser parser(input, &result->error, multiline, zone); | 4805 RegExpParser parser(input, &result->error, multiline, zone); |
| 4840 RegExpTree* tree = parser.ParsePattern(); | 4806 RegExpTree* tree = parser.ParsePattern(); |
| 4841 if (parser.failed()) { | 4807 if (parser.failed()) { |
| 4842 ASSERT(tree == NULL); | 4808 ASSERT(tree == NULL); |
| 4843 ASSERT(!result->error.is_null()); | 4809 ASSERT(!result->error.is_null()); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 4870 } | 4836 } |
| 4871 | 4837 |
| 4872 if (info()->is_lazy()) { | 4838 if (info()->is_lazy()) { |
| 4873 ASSERT(!info()->is_eval()); | 4839 ASSERT(!info()->is_eval()); |
| 4874 if (info()->shared_info()->is_function()) { | 4840 if (info()->shared_info()->is_function()) { |
| 4875 result = ParseLazy(); | 4841 result = ParseLazy(); |
| 4876 } else { | 4842 } else { |
| 4877 result = ParseProgram(); | 4843 result = ParseProgram(); |
| 4878 } | 4844 } |
| 4879 } else { | 4845 } else { |
| 4880 SetCachedData(info()->cached_data(), info()->cached_data_mode()); | 4846 SetCachedData(); |
| 4881 result = ParseProgram(); | 4847 result = ParseProgram(); |
| 4882 } | 4848 } |
| 4883 info()->SetFunction(result); | 4849 info()->SetFunction(result); |
| 4884 ASSERT(ast_value_factory_->IsInternalized()); | 4850 ASSERT(ast_value_factory_->IsInternalized()); |
| 4885 // info takes ownership of ast_value_factory_. | 4851 // info takes ownership of ast_value_factory_. |
| 4886 if (info()->ast_value_factory() == NULL) { | 4852 if (info()->ast_value_factory() == NULL) { |
| 4887 info()->SetAstValueFactory(ast_value_factory_); | 4853 info()->SetAstValueFactory(ast_value_factory_); |
| 4888 } | 4854 } |
| 4889 ast_value_factory_ = NULL; | 4855 ast_value_factory_ = NULL; |
| 4890 | 4856 |
| 4891 InternalizeUseCounts(); | 4857 InternalizeUseCounts(); |
| 4892 | 4858 |
| 4893 return (result != NULL); | 4859 return (result != NULL); |
| 4894 } | 4860 } |
| 4895 | 4861 |
| 4896 } } // namespace v8::internal | 4862 } } // namespace v8::internal |
| OLD | NEW |