Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(241)

Side by Side Diff: src/parser.cc

Issue 641283003: Support lazy parsing of inner functions (Closed) Base URL: https://chromium.googlesource.com/external/v8.git@bleeding_edge
Patch Set: Actually track variable declarations in the preparser Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parser.h ('k') | src/preparse-data.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/base/platform/platform.h" 10 #include "src/base/platform/platform.h"
11 #include "src/bootstrapper.h" 11 #include "src/bootstrapper.h"
12 #include "src/char-predicates-inl.h" 12 #include "src/char-predicates-inl.h"
13 #include "src/codegen.h" 13 #include "src/codegen.h"
14 #include "src/compiler.h" 14 #include "src/compiler.h"
15 #include "src/messages.h" 15 #include "src/messages.h"
16 #include "src/parser.h" 16 #include "src/parser.h"
17 #include "src/preparser.h" 17 #include "src/preparser.h"
18 #include "src/runtime/runtime.h" 18 #include "src/runtime/runtime.h"
19 #include "src/scanner-character-streams.h" 19 #include "src/scanner-character-streams.h"
20 #include "src/scopeinfo.h" 20 #include "src/scopeinfo.h"
21 #include "src/string-stream.h" 21 #include "src/string-stream.h"
22 22
23 namespace v8 { 23 namespace v8 {
24 namespace internal { 24 namespace internal {
25 25
26
27 int FunctionEntry::Size() {
28 if (backing_.is_empty()) return 0;
29 int result = kSize;
30 for (int i = 0; i < identifier_count(); i++) {
31 result += 1; // is_one_byte
32 CHECK(result < backing_.length());
33 const int byte_length = backing_[result];
34 const int word_length =
35 1 + (((byte_length * sizeof(unsigned char)) - 1) / sizeof(unsigned));
36 result += 1; // length
37 result += word_length;
38 }
39 CHECK(result <= backing_.length());
40 return result;
41 }
42
43
44 const AstRawString* FunctionEntry::IdentifierIterator::Next(
45 AstValueFactory* ast_value_factory) {
46 // FunctionEntry::size() is always called when an IdentifierIterator is
47 // constructed (by FunctionEntry::Identifiers), and FunctionEntry::size()
48 // CHECKs that the identifiers don't run past the end of backing_ so we don't
49 // have to CHECK that here.
50 DCHECK(!AtEnd());
51 const bool is_one_byte = static_cast<bool>(backing_.first());
52 backing_ += 1;
53 const int length = backing_.first();
54 backing_ += 1;
55 if (is_one_byte) {
56 Vector<const uint8_t> data = Vector<const uint8_t>::cast(backing_);
57 data.Truncate(length);
58 const int word_length =
59 1 + (((length * sizeof(uint8_t)) - 1) / sizeof(unsigned));
60 backing_ += word_length;
61 return ast_value_factory->GetOneByteString(data);
62 } else {
63 Vector<const uint16_t> data = Vector<const uint16_t>::cast(backing_);
64 data.Truncate(length);
65 const int word_length =
66 1 + (((length * sizeof(uint16_t)) - 1) / sizeof(unsigned));
67 backing_ += word_length;
68 return ast_value_factory->GetTwoByteString(data);
69 }
70 }
71
72
26 RegExpBuilder::RegExpBuilder(Zone* zone) 73 RegExpBuilder::RegExpBuilder(Zone* zone)
27 : zone_(zone), 74 : zone_(zone),
28 pending_empty_(false), 75 pending_empty_(false),
29 characters_(NULL), 76 characters_(NULL),
30 terms_(), 77 terms_(),
31 alternatives_() 78 alternatives_()
32 #ifdef DEBUG 79 #ifdef DEBUG
33 , last_added_(ADD_NONE) 80 , last_added_(ADD_NONE)
34 #endif 81 #endif
35 {} 82 {}
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 new(zone()) RegExpQuantifier(min, max, quantifier_type, atom), zone()); 228 new(zone()) RegExpQuantifier(min, max, quantifier_type, atom), zone());
182 LAST(ADD_TERM); 229 LAST(ADD_TERM);
183 } 230 }
184 231
185 232
186 FunctionEntry ParseData::GetFunctionEntry(int start) { 233 FunctionEntry ParseData::GetFunctionEntry(int start) {
187 // The current pre-data entry must be a FunctionEntry with the given 234 // The current pre-data entry must be a FunctionEntry with the given
188 // start position. 235 // start position.
189 if ((function_index_ + FunctionEntry::kSize <= Length()) && 236 if ((function_index_ + FunctionEntry::kSize <= Length()) &&
190 (static_cast<int>(Data()[function_index_]) == start)) { 237 (static_cast<int>(Data()[function_index_]) == start)) {
191 int index = function_index_; 238 int remaining_length = Length() - function_index_;
192 function_index_ += FunctionEntry::kSize; 239 Vector<unsigned> subvector(&(Data()[function_index_]), remaining_length);
193 Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize); 240 FunctionEntry entry(subvector);
194 return FunctionEntry(subvector); 241 int entry_size = entry.Size();
242 CHECK(entry_size <= remaining_length);
243 function_index_ += entry_size;
244 return entry;
195 } 245 }
196 return FunctionEntry(); 246 return FunctionEntry();
197 } 247 }
198 248
199 249
200 int ParseData::FunctionCount() { 250 int ParseData::FunctionCount() {
201 int functions_size = FunctionsSize(); 251 int function_count = 0;
202 if (functions_size < 0) return 0; 252 int function_index = PreparseDataConstants::kHeaderSize;
203 if (functions_size % FunctionEntry::kSize != 0) return 0; 253 while (function_index < Length()) {
204 return functions_size / FunctionEntry::kSize; 254 function_count += 1;
255 Vector<unsigned> subvector(&(Data()[function_index]),
256 Length() - function_index);
257 FunctionEntry entry(subvector);
258 function_index += entry.Size();
259 }
260 return function_count;
205 } 261 }
206 262
207 263
208 bool ParseData::IsSane() { 264 bool ParseData::IsSane() {
209 // Check that the header data is valid and doesn't specify 265 // Check that the header data is valid and doesn't specify
210 // point to positions outside the store. 266 // point to positions outside the store.
211 int data_length = Length(); 267 int data_length = Length();
212 if (data_length < PreparseDataConstants::kHeaderSize) return false; 268 if (data_length < PreparseDataConstants::kHeaderSize) return false;
213 if (Magic() != PreparseDataConstants::kMagicNumber) return false; 269 if (Magic() != PreparseDataConstants::kMagicNumber) return false;
214 if (Version() != PreparseDataConstants::kCurrentVersion) return false; 270 if (Version() != PreparseDataConstants::kCurrentVersion) return false;
215 if (HasError()) return false; 271 if (HasError()) return false;
216 // Check that the space allocated for function entries is sane. 272 // Check that the space allocated for function entries is sane.
217 int functions_size = FunctionsSize(); 273 int functions_size = FunctionsSize();
218 if (functions_size < 0) return false; 274 if (functions_size < 0) return false;
219 if (functions_size % FunctionEntry::kSize != 0) return false;
220 // Check that the total size has room for header and function entries. 275 // Check that the total size has room for header and function entries.
221 int minimum_size = 276 int minimum_size =
222 PreparseDataConstants::kHeaderSize + functions_size; 277 PreparseDataConstants::kHeaderSize + functions_size;
223 if (data_length < minimum_size) return false; 278 if (data_length < minimum_size) return false;
224 return true; 279 return true;
225 } 280 }
226 281
227 282
228 void ParseData::Initialize() { 283 void ParseData::Initialize() {
229 // Prepares state for use. 284 // Prepares state for use.
(...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 } 977 }
923 } 978 }
924 979
925 // Make sure the target stack is empty. 980 // Make sure the target stack is empty.
926 DCHECK(target_stack_ == NULL); 981 DCHECK(target_stack_ == NULL);
927 982
928 return result; 983 return result;
929 } 984 }
930 985
931 986
987 // This method is invoked by the runtime to re-parse the source of a lazily
988 // compiled function when that function gets called.
932 FunctionLiteral* Parser::ParseLazy() { 989 FunctionLiteral* Parser::ParseLazy() {
933 // It's OK to use the counters here, since this function is only called in 990 // It's OK to use the counters here, since this function is only called in
934 // the main thread. 991 // the main thread.
935 HistogramTimerScope timer_scope(isolate()->counters()->parse_lazy()); 992 HistogramTimerScope timer_scope(isolate()->counters()->parse_lazy());
936 Handle<String> source(String::cast(script()->source())); 993 Handle<String> source(String::cast(script()->source()));
937 isolate()->counters()->total_parse_size()->Increment(source->length()); 994 isolate()->counters()->total_parse_size()->Increment(source->length());
938 base::ElapsedTimer timer; 995 base::ElapsedTimer timer;
939 if (FLAG_trace_parse) { 996 if (FLAG_trace_parse) {
940 timer.Start(); 997 timer.Start();
941 } 998 }
(...skipping 2659 matching lines...) Expand 10 before | Expand all | Expand 10 after
3601 // lazy compilation are: 3658 // lazy compilation are:
3602 // - It must not have been prohibited by the caller to Parse (some callers 3659 // - It must not have been prohibited by the caller to Parse (some callers
3603 // need a full AST). 3660 // need a full AST).
3604 // - The outer scope must allow lazy compilation of inner functions. 3661 // - The outer scope must allow lazy compilation of inner functions.
3605 // - The function mustn't be a function expression with an open parenthesis 3662 // - The function mustn't be a function expression with an open parenthesis
3606 // before; we consider that a hint that the function will be called 3663 // before; we consider that a hint that the function will be called
3607 // immediately, and it would be a waste of time to make it lazily 3664 // immediately, and it would be a waste of time to make it lazily
3608 // compiled. 3665 // compiled.
3609 // These are all things we can know at this point, without looking at the 3666 // These are all things we can know at this point, without looking at the
3610 // function itself. 3667 // function itself.
3611 3668 bool is_lazily_parsed =
3612 // In addition, we need to distinguish between these cases: 3669 (mode() != PARSE_EAGERLY && scope_->AllowsLazyCompilation() &&
3613 // (function foo() { 3670 !parenthesized_function_);
3614 // bar = function() { return 1; }
3615 // })();
3616 // and
3617 // (function foo() {
3618 // var a = 1;
3619 // bar = function() { return a; }
3620 // })();
3621
3622 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
3623 // parenthesis before the function means that it will be called
3624 // immediately). The inner function *must* be parsed eagerly to resolve the
3625 // possible reference to the variable in foo's scope. However, it's possible
3626 // that it will be compiled lazily.
3627
3628 // To make this additional case work, both Parser and PreParser implement a
3629 // logic where only top-level functions will be parsed lazily.
3630 bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
3631 scope_->AllowsLazyCompilation() &&
3632 !parenthesized_function_);
3633 parenthesized_function_ = false; // The bit was set for this function only. 3671 parenthesized_function_ = false; // The bit was set for this function only.
3634 3672
3635 if (is_lazily_parsed) { 3673 if (is_lazily_parsed) {
3636 SkipLazyFunctionBody(function_name, &materialized_literal_count, 3674 SkipLazyFunctionBody(function_name, &materialized_literal_count,
3637 &expected_property_count, CHECK_OK); 3675 &expected_property_count, CHECK_OK);
3638 } else { 3676 } else {
3639 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, 3677 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
3640 is_generator, CHECK_OK); 3678 is_generator, CHECK_OK);
3641 materialized_literal_count = function_state.materialized_literal_count(); 3679 materialized_literal_count = function_state.materialized_literal_count();
3642 expected_property_count = function_state.expected_property_count(); 3680 expected_property_count = function_state.expected_property_count();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
3710 3748
3711 scope_->set_end_position(entry.end_pos()); 3749 scope_->set_end_position(entry.end_pos());
3712 Expect(Token::RBRACE, ok); 3750 Expect(Token::RBRACE, ok);
3713 if (!*ok) { 3751 if (!*ok) {
3714 return; 3752 return;
3715 } 3753 }
3716 total_preparse_skipped_ += scope_->end_position() - function_block_pos; 3754 total_preparse_skipped_ += scope_->end_position() - function_block_pos;
3717 *materialized_literal_count = entry.literal_count(); 3755 *materialized_literal_count = entry.literal_count();
3718 *expected_property_count = entry.property_count(); 3756 *expected_property_count = entry.property_count();
3719 scope_->SetStrictMode(entry.strict_mode()); 3757 scope_->SetStrictMode(entry.strict_mode());
3758 if (entry.calls_eval()) {
3759 // If there is a direct call to eval (ES5 10.4.2(2) / 15.1.2.1.1) then
3760 // every variable gets allocated and there's little point in keeping track
3761 // of which variables are accessed by nested functions.
3762 scope_->DeclarationScope()->RecordEvalCall();
3763 } else {
3764 FunctionEntry::IdentifierIterator it = entry.Identifiers();
3765 while (!it.AtEnd()) {
3766 ExpressionFromIdentifier(it.Next(ast_value_factory()),
3767 RelocInfo::kNoPosition, scope_, factory());
3768 }
3769 }
3720 } else { 3770 } else {
3721 // With no cached data, we partially parse the function, without building an 3771 // With no cached data, we partially parse the function, without building an
3722 // AST. This gathers the data needed to build a lazy function. 3772 // AST. This gathers the data needed to build a lazy function.
3723 SingletonLogger logger; 3773 SingletonLogger logger;
3724 PreParser::PreParseResult result = 3774 PreParser::PreParseResult result =
3725 ParseLazyFunctionBodyWithPreParser(&logger); 3775 ParseLazyFunctionBodyWithPreParser(&logger);
3726 if (result == PreParser::kPreParseStackOverflow) { 3776 if (result == PreParser::kPreParseStackOverflow) {
3727 // Propagate stack overflow. 3777 // Propagate stack overflow.
3728 set_stack_overflow(); 3778 set_stack_overflow();
3729 *ok = false; 3779 *ok = false;
3730 return; 3780 return;
3731 } 3781 }
3732 if (logger.has_error()) { 3782 if (logger.has_error()) {
3733 ParserTraits::ReportMessageAt( 3783 ParserTraits::ReportMessageAt(
3734 Scanner::Location(logger.start(), logger.end()), 3784 Scanner::Location(logger.start(), logger.end()),
3735 logger.message(), logger.argument_opt(), logger.is_reference_error()); 3785 logger.message(), logger.argument_opt(), logger.is_reference_error());
3736 *ok = false; 3786 *ok = false;
3737 return; 3787 return;
3738 } 3788 }
3739 scope_->set_end_position(logger.end()); 3789 scope_->set_end_position(logger.end());
3740 Expect(Token::RBRACE, ok); 3790 Expect(Token::RBRACE, ok);
3741 if (!*ok) { 3791 if (!*ok) {
3742 return; 3792 return;
3743 } 3793 }
3794
3795 if (logger.calls_eval()) {
3796 scope_->DeclarationScope()->RecordEvalCall();
3797 if (compile_options() == ScriptCompiler::kProduceParserCache) {
3798 DCHECK(log_);
3799 log_->LogEvalCall();
3800 }
3801 } else {
3802 SingletonLogger::IdentifierIterator it = logger.IdentifiersStart();
3803 for (const AstRawString* identifier = it.Next(); identifier != NULL;
3804 identifier = it.Next()) {
3805 // position doesn't matter here, we're only creating the expression
3806 // so we can track usage of variables
3807 ExpressionFromIdentifier(identifier, RelocInfo::kNoPosition, scope_,
3808 factory());
3809 if (compile_options() == ScriptCompiler::kProduceParserCache) {
3810 DCHECK(log_);
3811 log_->LogIdentifier(identifier);
3812 }
3813 }
3814 }
3815
3744 total_preparse_skipped_ += scope_->end_position() - function_block_pos; 3816 total_preparse_skipped_ += scope_->end_position() - function_block_pos;
3745 *materialized_literal_count = logger.literals(); 3817 *materialized_literal_count = logger.literals();
3746 *expected_property_count = logger.properties(); 3818 *expected_property_count = logger.properties();
3747 scope_->SetStrictMode(logger.strict_mode()); 3819 scope_->SetStrictMode(logger.strict_mode());
3748 if (compile_options() == ScriptCompiler::kProduceParserCache) { 3820 if (compile_options() == ScriptCompiler::kProduceParserCache) {
3749 DCHECK(log_); 3821 DCHECK(log_);
3750 // Position right after terminal '}'. 3822 // Position right after terminal '}'.
3751 int body_end = scanner()->location().end_pos; 3823 int body_end = scanner()->location().end_pos;
3752 log_->LogFunction(function_block_pos, body_end, 3824 log_->LogFunction(function_block_pos, body_end,
3753 *materialized_literal_count, 3825 *materialized_literal_count,
3754 *expected_property_count, 3826 *expected_property_count,
3755 scope_->strict_mode()); 3827 scope_->strict_mode());
3756 } 3828 }
3757 } 3829 }
3758 } 3830 }
3759 3831
3760 3832
3761 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( 3833 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
3762 const AstRawString* function_name, int pos, Variable* fvar, 3834 const AstRawString* function_name, int pos, Variable* fvar,
3763 Token::Value fvar_init_op, bool is_generator, bool* ok) { 3835 Token::Value fvar_init_op, bool is_generator, bool* ok) {
3764 // Everything inside an eagerly parsed function will be parsed eagerly 3836 // We can lazily parse functions enclosed in eagerly parsed functions but we
3765 // (see comment above). 3837 // have to keep track of what variables the inner functions access - or if the
3766 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); 3838 // the inner function calls eval (in which case we have to assume every
3839 // variable might be accessed inside the eval).
3840 Mode mode =
3841 (mode_ == PARSE_EAGERLY) ? PARSE_EAGERLY : PARSE_INNER_FUNCTION_LAZILY;
3842 ParsingModeScope parsing_mode(this, mode);
3843
3767 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8, zone()); 3844 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8, zone());
3768 if (fvar != NULL) { 3845 if (fvar != NULL) {
3769 VariableProxy* fproxy = scope_->NewUnresolved( 3846 VariableProxy* fproxy = scope_->NewUnresolved(
3770 factory(), function_name, Interface::NewConst()); 3847 factory(), function_name, Interface::NewConst());
3771 fproxy->BindTo(fvar); 3848 fproxy->BindTo(fvar);
3772 body->Add(factory()->NewExpressionStatement( 3849 body->Add(factory()->NewExpressionStatement(
3773 factory()->NewAssignment(fvar_init_op, 3850 factory()->NewAssignment(fvar_init_op,
3774 fproxy, 3851 fproxy,
3775 factory()->NewThisFunction(pos), 3852 factory()->NewThisFunction(pos),
3776 RelocInfo::kNoPosition), 3853 RelocInfo::kNoPosition),
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
3820 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( 3897 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
3821 SingletonLogger* logger) { 3898 SingletonLogger* logger) {
3822 // This function may be called on a background thread too; record only the 3899 // This function may be called on a background thread too; record only the
3823 // main thread preparse times. 3900 // main thread preparse times.
3824 if (pre_parse_timer_ != NULL) { 3901 if (pre_parse_timer_ != NULL) {
3825 pre_parse_timer_->Start(); 3902 pre_parse_timer_->Start();
3826 } 3903 }
3827 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); 3904 DCHECK_EQ(Token::LBRACE, scanner()->current_token());
3828 3905
3829 if (reusable_preparser_ == NULL) { 3906 if (reusable_preparser_ == NULL) {
3830 reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit_); 3907 reusable_preparser_ = new PreParser(&scanner_, NULL, ast_value_factory(),
3908 zone(), stack_limit_);
3831 reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping()); 3909 reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
3832 reusable_preparser_->set_allow_modules(allow_modules()); 3910 reusable_preparser_->set_allow_modules(allow_modules());
3833 reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax()); 3911 reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax());
3834 reusable_preparser_->set_allow_lazy(true); 3912 reusable_preparser_->set_allow_lazy(true);
3835 reusable_preparser_->set_allow_arrow_functions(allow_arrow_functions()); 3913 reusable_preparser_->set_allow_arrow_functions(allow_arrow_functions());
3836 reusable_preparser_->set_allow_harmony_numeric_literals( 3914 reusable_preparser_->set_allow_harmony_numeric_literals(
3837 allow_harmony_numeric_literals()); 3915 allow_harmony_numeric_literals());
3838 reusable_preparser_->set_allow_classes(allow_classes()); 3916 reusable_preparser_->set_allow_classes(allow_classes());
3839 reusable_preparser_->set_allow_harmony_object_literals( 3917 reusable_preparser_->set_allow_harmony_object_literals(
3840 allow_harmony_object_literals()); 3918 allow_harmony_object_literals());
3841 } 3919 }
3842 PreParser::PreParseResult result = 3920 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
3843 reusable_preparser_->PreParseLazyFunction(strict_mode(), 3921 strict_mode(), is_generator(), mode_ == PARSE_INNER_FUNCTION_LAZILY,
3844 is_generator(), 3922 logger);
3845 logger);
3846 if (pre_parse_timer_ != NULL) { 3923 if (pre_parse_timer_ != NULL) {
3847 pre_parse_timer_->Stop(); 3924 pre_parse_timer_->Stop();
3848 } 3925 }
3849 return result; 3926 return result;
3850 } 3927 }
3851 3928
3852 3929
3853 Expression* Parser::ParseV8Intrinsic(bool* ok) { 3930 Expression* Parser::ParseV8Intrinsic(bool* ok) {
3854 // CallRuntime :: 3931 // CallRuntime ::
3855 // '%' Identifier Arguments 3932 // '%' Identifier Arguments
(...skipping 1094 matching lines...) Expand 10 before | Expand all | Expand 10 after
4950 5027
4951 // We cannot internalize on a background thread; a foreground task will take 5028 // We cannot internalize on a background thread; a foreground task will take
4952 // care of calling Parser::Internalize just before compilation. 5029 // care of calling Parser::Internalize just before compilation.
4953 5030
4954 if (compile_options() == ScriptCompiler::kProduceParserCache) { 5031 if (compile_options() == ScriptCompiler::kProduceParserCache) {
4955 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); 5032 if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
4956 log_ = NULL; 5033 log_ = NULL;
4957 } 5034 }
4958 } 5035 }
4959 } } // namespace v8::internal 5036 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/preparse-data.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698