v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
parser.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "api.h"
31 #include "ast.h"
32 #include "bootstrapper.h"
33 #include "char-predicates-inl.h"
34 #include "codegen.h"
35 #include "compiler.h"
36 #include "messages.h"
37 #include "parser.h"
38 #include "platform.h"
39 #include "preparser.h"
40 #include "runtime.h"
42 #include "scopeinfo.h"
43 #include "string-stream.h"
44 
45 namespace v8 {
46 namespace internal {
47 
49  : zone_(zone),
50  pending_empty_(false),
51  characters_(NULL),
52  terms_(),
53  alternatives_()
54 #ifdef DEBUG
55  , last_added_(ADD_NONE)
56 #endif
57  {}
58 
59 
60 void RegExpBuilder::FlushCharacters() {
61  pending_empty_ = false;
62  if (characters_ != NULL) {
63  RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector());
64  characters_ = NULL;
65  text_.Add(atom, zone());
66  LAST(ADD_ATOM);
67  }
68 }
69 
70 
71 void RegExpBuilder::FlushText() {
72  FlushCharacters();
73  int num_text = text_.length();
74  if (num_text == 0) {
75  return;
76  } else if (num_text == 1) {
77  terms_.Add(text_.last(), zone());
78  } else {
79  RegExpText* text = new(zone()) RegExpText(zone());
80  for (int i = 0; i < num_text; i++)
81  text_.Get(i)->AppendToText(text, zone());
82  terms_.Add(text, zone());
83  }
84  text_.Clear();
85 }
86 
87 
89  pending_empty_ = false;
90  if (characters_ == NULL) {
91  characters_ = new(zone()) ZoneList<uc16>(4, zone());
92  }
93  characters_->Add(c, zone());
94  LAST(ADD_CHAR);
95 }
96 
97 
99  pending_empty_ = true;
100 }
101 
102 
104  if (term->IsEmpty()) {
105  AddEmpty();
106  return;
107  }
108  if (term->IsTextElement()) {
109  FlushCharacters();
110  text_.Add(term, zone());
111  } else {
112  FlushText();
113  terms_.Add(term, zone());
114  }
115  LAST(ADD_ATOM);
116 }
117 
118 
120  FlushText();
121  terms_.Add(assert, zone());
122  LAST(ADD_ASSERT);
123 }
124 
125 
127  FlushTerms();
128 }
129 
130 
131 void RegExpBuilder::FlushTerms() {
132  FlushText();
133  int num_terms = terms_.length();
134  RegExpTree* alternative;
135  if (num_terms == 0) {
136  alternative = RegExpEmpty::GetInstance();
137  } else if (num_terms == 1) {
138  alternative = terms_.last();
139  } else {
140  alternative = new(zone()) RegExpAlternative(terms_.GetList(zone()));
141  }
142  alternatives_.Add(alternative, zone());
143  terms_.Clear();
144  LAST(ADD_NONE);
145 }
146 
147 
149  FlushTerms();
150  int num_alternatives = alternatives_.length();
151  if (num_alternatives == 0) {
152  return RegExpEmpty::GetInstance();
153  }
154  if (num_alternatives == 1) {
155  return alternatives_.last();
156  }
157  return new(zone()) RegExpDisjunction(alternatives_.GetList(zone()));
158 }
159 
160 
162  int min, int max, RegExpQuantifier::QuantifierType quantifier_type) {
163  if (pending_empty_) {
164  pending_empty_ = false;
165  return;
166  }
167  RegExpTree* atom;
168  if (characters_ != NULL) {
169  ASSERT(last_added_ == ADD_CHAR);
170  // Last atom was character.
171  Vector<const uc16> char_vector = characters_->ToConstVector();
172  int num_chars = char_vector.length();
173  if (num_chars > 1) {
174  Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
175  text_.Add(new(zone()) RegExpAtom(prefix), zone());
176  char_vector = char_vector.SubVector(num_chars - 1, num_chars);
177  }
178  characters_ = NULL;
179  atom = new(zone()) RegExpAtom(char_vector);
180  FlushText();
181  } else if (text_.length() > 0) {
182  ASSERT(last_added_ == ADD_ATOM);
183  atom = text_.RemoveLast();
184  FlushText();
185  } else if (terms_.length() > 0) {
186  ASSERT(last_added_ == ADD_ATOM);
187  atom = terms_.RemoveLast();
188  if (atom->max_match() == 0) {
189  // Guaranteed to only match an empty string.
190  LAST(ADD_TERM);
191  if (min == 0) {
192  return;
193  }
194  terms_.Add(atom, zone());
195  return;
196  }
197  } else {
198  // Only call immediately after adding an atom or character!
199  UNREACHABLE();
200  return;
201  }
202  terms_.Add(
203  new(zone()) RegExpQuantifier(min, max, quantifier_type, atom), zone());
204  LAST(ADD_TERM);
205 }
206 
207 
208 Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
209  // Make sure the cache is large enough to hold the symbol identifier.
210  if (symbol_cache_.length() <= symbol_id) {
211  // Increase length to index + 1.
212  symbol_cache_.AddBlock(Handle<String>::null(),
213  symbol_id + 1 - symbol_cache_.length(), zone());
214  }
215  Handle<String> result = symbol_cache_.at(symbol_id);
216  if (result.is_null()) {
217  result = scanner()->AllocateInternalizedString(isolate_);
218  ASSERT(!result.is_null());
219  symbol_cache_.at(symbol_id) = result;
220  return result;
221  }
222  isolate()->counters()->total_preparse_symbols_skipped()->Increment();
223  return result;
224 }
225 
226 
227 FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
228  // The current pre-data entry must be a FunctionEntry with the given
229  // start position.
230  if ((function_index_ + FunctionEntry::kSize <= store_.length())
231  && (static_cast<int>(store_[function_index_]) == start)) {
232  int index = function_index_;
233  function_index_ += FunctionEntry::kSize;
234  return FunctionEntry(store_.SubVector(index,
235  index + FunctionEntry::kSize));
236  }
237  return FunctionEntry();
238 }
239 
240 
242  return ReadNumber(&symbol_data_);
243 }
244 
245 
247  // Check that the header data is valid and doesn't specify
248  // point to positions outside the store.
249  if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
250  if (magic() != PreparseDataConstants::kMagicNumber) return false;
251  if (version() != PreparseDataConstants::kCurrentVersion) return false;
252  if (has_error()) {
253  // Extra sane sanity check for error message encoding.
256  return false;
257  }
260  return false;
261  }
262  unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
264  for (unsigned int i = 0; i <= arg_count; i++) {
265  if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
266  return false;
267  }
268  int length = static_cast<int>(Read(pos));
269  if (length < 0) return false;
270  pos += 1 + length;
271  }
272  if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
273  return false;
274  }
275  return true;
276  }
277  // Check that the space allocated for function entries is sane.
278  int functions_size =
279  static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
280  if (functions_size < 0) return false;
281  if (functions_size % FunctionEntry::kSize != 0) return false;
282  // Check that the count of symbols is non-negative.
283  int symbol_count =
284  static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
285  if (symbol_count < 0) return false;
286  // Check that the total size has room for header and function entries.
287  int minimum_size =
288  PreparseDataConstants::kHeaderSize + functions_size;
289  if (store_.length() < minimum_size) return false;
290  return true;
291 }
292 
293 
294 
295 const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
296  int length = start[0];
297  char* result = NewArray<char>(length + 1);
298  for (int i = 0; i < length; i++) {
299  result[i] = start[i + 1];
300  }
301  result[length] = '\0';
302  if (chars != NULL) *chars = length;
303  return result;
304 }
305 
306 
308  int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
309  int end_pos = Read(PreparseDataConstants::kMessageEndPos);
310  return Scanner::Location(beg_pos, end_pos);
311 }
312 
313 
315  unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
316  return ReadString(start, NULL);
317 }
318 
319 
321  int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
322  const char** array = NewArray<const char*>(arg_count);
323  // Position after text found by skipping past length field and
324  // length field content words.
327  for (int i = 0; i < arg_count; i++) {
328  int count = 0;
329  array[i] = ReadString(ReadAddress(pos), &count);
330  pos += count + 1;
331  }
332  return Vector<const char*>(array, arg_count);
333 }
334 
335 
336 unsigned ScriptDataImpl::Read(int position) {
337  return store_[PreparseDataConstants::kHeaderSize + position];
338 }
339 
340 
341 unsigned* ScriptDataImpl::ReadAddress(int position) {
342  return &store_[PreparseDataConstants::kHeaderSize + position];
343 }
344 
345 
346 Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) {
347  Scope* result = new(zone()) Scope(parent, scope_type, zone());
348  result->Initialize();
349  return result;
350 }
351 
352 
353 // ----------------------------------------------------------------------------
354 // Target is a support class to facilitate manipulation of the
355 // Parser's target_stack_ (the stack of potential 'break' and
356 // 'continue' statement targets). Upon construction, a new target is
357 // added; it is removed upon destruction.
358 
359 class Target BASE_EMBEDDED {
360  public:
361  Target(Target** variable, AstNode* node)
362  : variable_(variable), node_(node), previous_(*variable) {
363  *variable = this;
364  }
365 
367  *variable_ = previous_;
368  }
369 
370  Target* previous() { return previous_; }
371  AstNode* node() { return node_; }
372 
373  private:
374  Target** variable_;
375  AstNode* node_;
376  Target* previous_;
377 };
378 
379 
380 class TargetScope BASE_EMBEDDED {
381  public:
382  explicit TargetScope(Target** variable)
383  : variable_(variable), previous_(*variable) {
384  *variable = NULL;
385  }
386 
388  *variable_ = previous_;
389  }
390 
391  private:
392  Target** variable_;
393  Target* previous_;
394 };
395 
396 
397 // ----------------------------------------------------------------------------
398 // The CHECK_OK macro is a convenient macro to enforce error
399 // handling for functions that may fail (by returning !*ok).
400 //
401 // CAUTION: This macro appends extra statements after a call,
402 // thus it must never be used where only a single statement
403 // is correct (e.g. an if statement branch w/o braces)!
404 
405 #define CHECK_OK ok); \
406  if (!*ok) return NULL; \
407  ((void)0
408 #define DUMMY ) // to make indentation work
409 #undef DUMMY
410 
411 #define CHECK_FAILED ); \
412  if (failed_) return NULL; \
413  ((void)0
414 #define DUMMY ) // to make indentation work
415 #undef DUMMY
416 
417 // ----------------------------------------------------------------------------
418 // Implementation of Parser
419 
421  return identifier.is_identical_to(
422  parser_->isolate()->factory()->eval_string()) ||
423  identifier.is_identical_to(
424  parser_->isolate()->factory()->arguments_string());
425 }
426 
427 
429  ASSERT(expression != NULL);
430  Property* property = expression->AsProperty();
431  return property != NULL &&
432  property->obj()->AsVariableProxy() != NULL &&
433  property->obj()->AsVariableProxy()->is_this();
434 }
435 
436 
438  VariableProxy* operand = expression->AsVariableProxy();
439  return operand != NULL && !operand->is_this();
440 }
441 
442 
444  Expression* expression) {
445  if (expression->IsPropertyName()) {
446  fni->PushLiteralName(expression->AsLiteral()->AsPropertyName());
447  } else {
448  fni->PushLiteralName(
449  parser_->isolate()->factory()->anonymous_function_string());
450  }
451 }
452 
453 
455  Expression* right) {
456  ASSERT(left != NULL);
457  if (left->AsProperty() != NULL &&
458  right->AsFunctionLiteral() != NULL) {
459  right->AsFunctionLiteral()->set_pretenure();
460  }
461 }
462 
463 
465  Scope* scope) {
466  VariableProxy* callee = expression->AsVariableProxy();
467  if (callee != NULL &&
468  callee->IsVariable(parser_->isolate()->factory()->eval_string())) {
469  scope->DeclarationScope()->RecordEvalCall();
470  }
471 }
472 
473 
475  VariableProxy* proxy = expression != NULL
476  ? expression->AsVariableProxy()
477  : NULL;
478  if (proxy != NULL) proxy->MarkAsLValue();
479  return expression;
480 }
481 
482 
484  bool* ok) {
485  VariableProxy* lhs = expression != NULL
486  ? expression->AsVariableProxy()
487  : NULL;
488  if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
489  parser_->ReportMessage("strict_eval_arguments",
491  *ok = false;
492  }
493 }
494 
495 
497  Expression** x, Expression* y, Token::Value op, int pos,
499  if ((*x)->AsLiteral() && (*x)->AsLiteral()->value()->IsNumber() &&
500  y->AsLiteral() && y->AsLiteral()->value()->IsNumber()) {
501  double x_val = (*x)->AsLiteral()->value()->Number();
502  double y_val = y->AsLiteral()->value()->Number();
503  switch (op) {
504  case Token::ADD:
505  *x = factory->NewNumberLiteral(x_val + y_val, pos);
506  return true;
507  case Token::SUB:
508  *x = factory->NewNumberLiteral(x_val - y_val, pos);
509  return true;
510  case Token::MUL:
511  *x = factory->NewNumberLiteral(x_val * y_val, pos);
512  return true;
513  case Token::DIV:
514  *x = factory->NewNumberLiteral(x_val / y_val, pos);
515  return true;
516  case Token::BIT_OR: {
517  int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
518  *x = factory->NewNumberLiteral(value, pos);
519  return true;
520  }
521  case Token::BIT_AND: {
522  int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
523  *x = factory->NewNumberLiteral(value, pos);
524  return true;
525  }
526  case Token::BIT_XOR: {
527  int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
528  *x = factory->NewNumberLiteral(value, pos);
529  return true;
530  }
531  case Token::SHL: {
532  int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
533  *x = factory->NewNumberLiteral(value, pos);
534  return true;
535  }
536  case Token::SHR: {
537  uint32_t shift = DoubleToInt32(y_val) & 0x1f;
538  uint32_t value = DoubleToUint32(x_val) >> shift;
539  *x = factory->NewNumberLiteral(value, pos);
540  return true;
541  }
542  case Token::SAR: {
543  uint32_t shift = DoubleToInt32(y_val) & 0x1f;
544  int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
545  *x = factory->NewNumberLiteral(value, pos);
546  return true;
547  }
548  default:
549  break;
550  }
551  }
552  return false;
553 }
554 
555 
557  Expression* expression, Token::Value op, int pos,
559  ASSERT(expression != NULL);
560  if (expression->AsLiteral() != NULL) {
561  Handle<Object> literal = expression->AsLiteral()->value();
562  if (op == Token::NOT) {
563  // Convert the literal to a boolean condition and negate it.
564  bool condition = literal->BooleanValue();
565  Handle<Object> result =
566  parser_->isolate()->factory()->ToBoolean(!condition);
567  return factory->NewLiteral(result, pos);
568  } else if (literal->IsNumber()) {
569  // Compute some expressions involving only number literals.
570  double value = literal->Number();
571  switch (op) {
572  case Token::ADD:
573  return expression;
574  case Token::SUB:
575  return factory->NewNumberLiteral(-value, pos);
576  case Token::BIT_NOT:
577  return factory->NewNumberLiteral(~DoubleToInt32(value), pos);
578  default:
579  break;
580  }
581  }
582  }
583  // Desugar '+foo' => 'foo*1'
584  if (op == Token::ADD) {
585  return factory->NewBinaryOperation(
586  Token::MUL, expression, factory->NewNumberLiteral(1, pos), pos);
587  }
588  // The same idea for '-foo' => 'foo*(-1)'.
589  if (op == Token::SUB) {
590  return factory->NewBinaryOperation(
591  Token::MUL, expression, factory->NewNumberLiteral(-1, pos), pos);
592  }
593  // ...and one more time for '~foo' => 'foo^(~0)'.
594  if (op == Token::BIT_NOT) {
595  return factory->NewBinaryOperation(
596  Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos);
597  }
598  return factory->NewUnaryOperation(op, expression, pos);
599 }
600 
601 
603  const char* message,
604  Vector<const char*> args,
605  bool is_reference_error) {
606  if (parser_->stack_overflow()) {
607  // Suppress the error message (syntax error or such) in the presence of a
608  // stack overflow. The isolate allows only one pending exception at at time
609  // and we want to report the stack overflow later.
610  return;
611  }
612  MessageLocation location(parser_->script_,
613  source_location.beg_pos,
614  source_location.end_pos);
615  Factory* factory = parser_->isolate()->factory();
616  Handle<FixedArray> elements = factory->NewFixedArray(args.length());
617  for (int i = 0; i < args.length(); i++) {
618  Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
619  ASSERT(!arg_string.is_null());
620  elements->set(i, *arg_string);
621  }
622  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
623  Handle<Object> result = is_reference_error
624  ? factory->NewReferenceError(message, array)
625  : factory->NewSyntaxError(message, array);
626  parser_->isolate()->Throw(*result, &location);
627 }
628 
629 
631  Vector<Handle<String> > args,
632  bool is_reference_error) {
633  Scanner::Location source_location = parser_->scanner()->location();
634  ReportMessageAt(source_location, message, args, is_reference_error);
635 }
636 
637 
639  const char* message,
640  Vector<Handle<String> > args,
641  bool is_reference_error) {
642  if (parser_->stack_overflow()) {
643  // Suppress the error message (syntax error or such) in the presence of a
644  // stack overflow. The isolate allows only one pending exception at at time
645  // and we want to report the stack overflow later.
646  return;
647  }
648  MessageLocation location(parser_->script_,
649  source_location.beg_pos,
650  source_location.end_pos);
651  Factory* factory = parser_->isolate()->factory();
652  Handle<FixedArray> elements = factory->NewFixedArray(args.length());
653  for (int i = 0; i < args.length(); i++) {
654  elements->set(i, *args[i]);
655  }
656  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
657  Handle<Object> result = is_reference_error
658  ? factory->NewReferenceError(message, array)
659  : factory->NewSyntaxError(message, array);
660  parser_->isolate()->Throw(*result, &location);
661 }
662 
663 
665  if (parser_->cached_data_mode() == CONSUME_CACHED_DATA) {
666  int symbol_id = (*parser_->cached_data())->GetSymbolIdentifier();
667  // If there is no symbol data, -1 will be returned.
668  if (symbol_id >= 0 &&
669  symbol_id < (*parser_->cached_data())->symbol_count()) {
670  return parser_->LookupCachedSymbol(symbol_id);
671  }
672  } else if (parser_->cached_data_mode() == PRODUCE_CACHED_DATA) {
673  if (parser_->log_->ShouldLogSymbols()) {
674  parser_->scanner()->LogSymbol(parser_->log_, parser_->position());
675  }
676  }
677  Handle<String> result =
678  parser_->scanner()->AllocateInternalizedString(parser_->isolate_);
679  ASSERT(!result.is_null());
680  return result;
681 }
682 
683 
685  PretenureFlag tenured) {
686  return scanner->AllocateNextLiteralString(parser_->isolate(), tenured);
687 }
688 
689 
691  Scope* scope,
693  return factory->NewVariableProxy(scope->receiver());
694 }
695 
696 
698  Token::Value token, int pos,
699  Scanner* scanner,
701  Factory* isolate_factory = parser_->isolate()->factory();
702  switch (token) {
703  case Token::NULL_LITERAL:
704  return factory->NewLiteral(isolate_factory->null_value(), pos);
705  case Token::TRUE_LITERAL:
706  return factory->NewLiteral(isolate_factory->true_value(), pos);
707  case Token::FALSE_LITERAL:
708  return factory->NewLiteral(isolate_factory->false_value(), pos);
709  case Token::NUMBER: {
710  double value = scanner->DoubleValue();
711  return factory->NewNumberLiteral(value, pos);
712  }
713  default:
714  ASSERT(false);
715  }
716  return NULL;
717 }
718 
719 
721  Handle<String> name, int pos, Scope* scope,
723  if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
724  // The name may refer to a module instance object, so its type is unknown.
725 #ifdef DEBUG
726  if (FLAG_print_interface_details)
727  PrintF("# Variable %s ", name->ToAsciiArray());
728 #endif
729  Interface* interface = Interface::NewUnknown(parser_->zone());
730  return scope->NewUnresolved(factory, name, interface, pos);
731 }
732 
733 
735  int pos, Scanner* scanner,
737  Handle<String> symbol = GetSymbol(scanner);
738  if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
739  return factory->NewLiteral(symbol, pos);
740 }
741 
742 
744  int position, AstNodeFactory<AstConstructionVisitor>* factory) {
745  return factory->NewLiteral(parser_->isolate()->factory()->the_hole_value(),
746  RelocInfo::kNoPosition);
747 }
748 
749 
751  return parser_->ParseV8Intrinsic(ok);
752 }
753 
754 
757  Scanner::Location function_name_location,
758  bool name_is_strict_reserved,
759  bool is_generator,
760  int function_token_position,
761  FunctionLiteral::FunctionType type,
762  bool* ok) {
763  return parser_->ParseFunctionLiteral(name, function_name_location,
764  name_is_strict_reserved, is_generator,
765  function_token_position, type, ok);
766 }
767 
768 
770  : ParserBase<ParserTraits>(&scanner_,
771  info->isolate()->stack_guard()->real_climit(),
772  info->extension(),
773  NULL,
774  info->zone(),
775  this),
776  isolate_(info->isolate()),
777  symbol_cache_(0, info->zone()),
778  script_(info->script()),
779  scanner_(isolate_->unicode_cache()),
780  reusable_preparser_(NULL),
781  original_scope_(NULL),
782  target_stack_(NULL),
783  cached_data_(NULL),
784  cached_data_mode_(NO_CACHED_DATA),
785  info_(info) {
786  ASSERT(!script_.is_null());
787  isolate_->set_ast_node_id(0);
788  set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
789  set_allow_modules(!info->is_native() && FLAG_harmony_modules);
790  set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native());
791  set_allow_lazy(false); // Must be explicitly enabled.
792  set_allow_generators(FLAG_harmony_generators);
793  set_allow_for_of(FLAG_harmony_iteration);
794  set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
795 }
796 
797 
798 FunctionLiteral* Parser::ParseProgram() {
799  // TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
800  // see comment for HistogramTimerScope class.
801  HistogramTimerScope timer_scope(isolate()->counters()->parse(), true);
802  Handle<String> source(String::cast(script_->source()));
803  isolate()->counters()->total_parse_size()->Increment(source->length());
804  ElapsedTimer timer;
805  if (FLAG_trace_parse) {
806  timer.Start();
807  }
808  fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
809 
810  // Initialize parser state.
811  CompleteParserRecorder recorder;
812  if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
813  log_ = &recorder;
814  } else if (cached_data_mode_ == CONSUME_CACHED_DATA) {
815  (*cached_data_)->Initialize();
816  }
817 
818  source->TryFlatten();
819  FunctionLiteral* result;
820  if (source->IsExternalTwoByteString()) {
821  // Notice that the stream is destroyed at the end of the branch block.
822  // The last line of the blocks can't be moved outside, even though they're
823  // identical calls.
824  ExternalTwoByteStringUtf16CharacterStream stream(
825  Handle<ExternalTwoByteString>::cast(source), 0, source->length());
826  scanner_.Initialize(&stream);
827  result = DoParseProgram(info(), source);
828  } else {
829  GenericStringUtf16CharacterStream stream(source, 0, source->length());
830  scanner_.Initialize(&stream);
831  result = DoParseProgram(info(), source);
832  }
833 
834  if (FLAG_trace_parse && result != NULL) {
835  double ms = timer.Elapsed().InMillisecondsF();
836  if (info()->is_eval()) {
837  PrintF("[parsing eval");
838  } else if (info()->script()->name()->IsString()) {
839  String* name = String::cast(info()->script()->name());
840  SmartArrayPointer<char> name_chars = name->ToCString();
841  PrintF("[parsing script: %s", name_chars.get());
842  } else {
843  PrintF("[parsing script");
844  }
845  PrintF(" - took %0.3f ms]\n", ms);
846  }
847  if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
848  Vector<unsigned> store = recorder.ExtractData();
849  *cached_data_ = new ScriptDataImpl(store);
850  log_ = NULL;
851  }
852  return result;
853 }
854 
855 
856 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
857  Handle<String> source) {
858  ASSERT(scope_ == NULL);
859  ASSERT(target_stack_ == NULL);
860 
861  Handle<String> no_name = isolate()->factory()->empty_string();
862 
863  FunctionLiteral* result = NULL;
864  { Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
865  info->SetGlobalScope(scope);
866  if (!info->context().is_null()) {
867  scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
868  }
869  original_scope_ = scope;
870  if (info->is_eval()) {
871  if (!scope->is_global_scope() || info->strict_mode() == STRICT) {
872  scope = NewScope(scope, EVAL_SCOPE);
873  }
874  } else if (info->is_global()) {
875  scope = NewScope(scope, GLOBAL_SCOPE);
876  }
877  scope->set_start_position(0);
878  scope->set_end_position(source->length());
879 
880  // Compute the parsing mode.
881  Mode mode = (FLAG_lazy && allow_lazy()) ? PARSE_LAZILY : PARSE_EAGERLY;
882  if (allow_natives_syntax() ||
883  extension_ != NULL ||
884  scope->is_eval_scope()) {
885  mode = PARSE_EAGERLY;
886  }
887  ParsingModeScope parsing_mode(this, mode);
888 
889  // Enters 'scope'.
890  FunctionState function_state(&function_state_, &scope_, scope, zone());
891 
892  scope_->SetStrictMode(info->strict_mode());
893  ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
894  bool ok = true;
895  int beg_pos = scanner()->location().beg_pos;
896  ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok);
897  if (ok && strict_mode() == STRICT) {
898  CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
899  }
900 
901  if (ok && allow_harmony_scoping() && strict_mode() == STRICT) {
902  CheckConflictingVarDeclarations(scope_, &ok);
903  }
904 
905  if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
906  if (body->length() != 1 ||
907  !body->at(0)->IsExpressionStatement() ||
908  !body->at(0)->AsExpressionStatement()->
909  expression()->IsFunctionLiteral()) {
910  ReportMessage("single_function_literal", Vector<const char*>::empty());
911  ok = false;
912  }
913  }
914 
915  if (ok) {
916  result = factory()->NewFunctionLiteral(
917  no_name,
918  scope_,
919  body,
920  function_state.materialized_literal_count(),
921  function_state.expected_property_count(),
922  function_state.handler_count(),
923  0,
924  FunctionLiteral::kNoDuplicateParameters,
925  FunctionLiteral::ANONYMOUS_EXPRESSION,
926  FunctionLiteral::kGlobalOrEval,
927  FunctionLiteral::kNotParenthesized,
928  FunctionLiteral::kNotGenerator,
929  0);
930  result->set_ast_properties(factory()->visitor()->ast_properties());
931  result->set_slot_processor(factory()->visitor()->slot_processor());
932  result->set_dont_optimize_reason(
933  factory()->visitor()->dont_optimize_reason());
934  } else if (stack_overflow()) {
935  isolate()->StackOverflow();
936  }
937  }
938 
939  // Make sure the target stack is empty.
940  ASSERT(target_stack_ == NULL);
941 
942  return result;
943 }
944 
945 
946 FunctionLiteral* Parser::ParseLazy() {
947  HistogramTimerScope timer_scope(isolate()->counters()->parse_lazy());
948  Handle<String> source(String::cast(script_->source()));
949  isolate()->counters()->total_parse_size()->Increment(source->length());
950  ElapsedTimer timer;
951  if (FLAG_trace_parse) {
952  timer.Start();
953  }
954  Handle<SharedFunctionInfo> shared_info = info()->shared_info();
955 
956  // Initialize parser state.
957  source->TryFlatten();
958  FunctionLiteral* result;
959  if (source->IsExternalTwoByteString()) {
960  ExternalTwoByteStringUtf16CharacterStream stream(
961  Handle<ExternalTwoByteString>::cast(source),
962  shared_info->start_position(),
963  shared_info->end_position());
964  result = ParseLazy(&stream);
965  } else {
966  GenericStringUtf16CharacterStream stream(source,
967  shared_info->start_position(),
968  shared_info->end_position());
969  result = ParseLazy(&stream);
970  }
971 
972  if (FLAG_trace_parse && result != NULL) {
973  double ms = timer.Elapsed().InMillisecondsF();
974  SmartArrayPointer<char> name_chars = result->debug_name()->ToCString();
975  PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms);
976  }
977  return result;
978 }
979 
980 
981 FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
982  Handle<SharedFunctionInfo> shared_info = info()->shared_info();
983  scanner_.Initialize(source);
984  ASSERT(scope_ == NULL);
985  ASSERT(target_stack_ == NULL);
986 
987  Handle<String> name(String::cast(shared_info->name()));
988  fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
989  fni_->PushEnclosingName(name);
990 
991  ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
992 
993  // Place holder for the result.
994  FunctionLiteral* result = NULL;
995 
996  {
997  // Parse the function literal.
998  Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
999  info()->SetGlobalScope(scope);
1000  if (!info()->closure().is_null()) {
1001  scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope,
1002  zone());
1003  }
1004  original_scope_ = scope;
1005  FunctionState function_state(&function_state_, &scope_, scope, zone());
1006  ASSERT(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT);
1007  ASSERT(info()->strict_mode() == shared_info->strict_mode());
1008  scope->SetStrictMode(shared_info->strict_mode());
1009  FunctionLiteral::FunctionType function_type = shared_info->is_expression()
1010  ? (shared_info->is_anonymous()
1011  ? FunctionLiteral::ANONYMOUS_EXPRESSION
1012  : FunctionLiteral::NAMED_EXPRESSION)
1013  : FunctionLiteral::DECLARATION;
1014  bool ok = true;
1015  result = ParseFunctionLiteral(name,
1017  false, // Strict mode name already checked.
1018  shared_info->is_generator(),
1019  RelocInfo::kNoPosition,
1020  function_type,
1021  &ok);
1022  // Make sure the results agree.
1023  ASSERT(ok == (result != NULL));
1024  }
1025 
1026  // Make sure the target stack is empty.
1027  ASSERT(target_stack_ == NULL);
1028 
1029  if (result == NULL) {
1030  if (stack_overflow()) isolate()->StackOverflow();
1031  } else {
1032  Handle<String> inferred_name(shared_info->inferred_name());
1033  result->set_inferred_name(inferred_name);
1034  }
1035  return result;
1036 }
1037 
1038 
1039 void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
1040  int end_token,
1041  bool is_eval,
1042  bool is_global,
1043  bool* ok) {
1044  // SourceElements ::
1045  // (ModuleElement)* <end_token>
1046 
1047  // Allocate a target stack to use for this set of source
1048  // elements. This way, all scripts and functions get their own
1049  // target stack thus avoiding illegal breaks and continues across
1050  // functions.
1051  TargetScope scope(&this->target_stack_);
1052 
1053  ASSERT(processor != NULL);
1054  bool directive_prologue = true; // Parsing directive prologue.
1055 
1056  while (peek() != end_token) {
1057  if (directive_prologue && peek() != Token::STRING) {
1058  directive_prologue = false;
1059  }
1060 
1061  Scanner::Location token_loc = scanner()->peek_location();
1062  Statement* stat;
1063  if (is_global && !is_eval) {
1064  stat = ParseModuleElement(NULL, CHECK_OK);
1065  } else {
1066  stat = ParseBlockElement(NULL, CHECK_OK);
1067  }
1068  if (stat == NULL || stat->IsEmpty()) {
1069  directive_prologue = false; // End of directive prologue.
1070  continue;
1071  }
1072 
1073  if (directive_prologue) {
1074  // A shot at a directive.
1075  ExpressionStatement* e_stat;
1076  Literal* literal;
1077  // Still processing directive prologue?
1078  if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1079  (literal = e_stat->expression()->AsLiteral()) != NULL &&
1080  literal->value()->IsString()) {
1081  Handle<String> directive = Handle<String>::cast(literal->value());
1082 
1083  // Check "use strict" directive (ES5 14.1).
1084  if (strict_mode() == SLOPPY &&
1085  directive->Equals(isolate()->heap()->use_strict_string()) &&
1086  token_loc.end_pos - token_loc.beg_pos ==
1087  isolate()->heap()->use_strict_string()->length() + 2) {
1088  // TODO(mstarzinger): Global strict eval calls, need their own scope
1089  // as specified in ES5 10.4.2(3). The correct fix would be to always
1090  // add this scope in DoParseProgram(), but that requires adaptations
1091  // all over the code base, so we go with a quick-fix for now.
1092  // In the same manner, we have to patch the parsing mode.
1093  if (is_eval && !scope_->is_eval_scope()) {
1094  ASSERT(scope_->is_global_scope());
1095  Scope* scope = NewScope(scope_, EVAL_SCOPE);
1096  scope->set_start_position(scope_->start_position());
1097  scope->set_end_position(scope_->end_position());
1098  scope_ = scope;
1099  mode_ = PARSE_EAGERLY;
1100  }
1101  scope_->SetStrictMode(STRICT);
1102  // "use strict" is the only directive for now.
1103  directive_prologue = false;
1104  }
1105  } else {
1106  // End of the directive prologue.
1107  directive_prologue = false;
1108  }
1109  }
1110 
1111  processor->Add(stat, zone());
1112  }
1113 
1114  return 0;
1115 }
1116 
1117 
1118 Statement* Parser::ParseModuleElement(ZoneStringList* labels,
1119  bool* ok) {
1120  // (Ecma 262 5th Edition, clause 14):
1121  // SourceElement:
1122  // Statement
1123  // FunctionDeclaration
1124  //
1125  // In harmony mode we allow additionally the following productions
1126  // ModuleElement:
1127  // LetDeclaration
1128  // ConstDeclaration
1129  // ModuleDeclaration
1130  // ImportDeclaration
1131  // ExportDeclaration
1132  // GeneratorDeclaration
1133 
1134  switch (peek()) {
1135  case Token::FUNCTION:
1136  return ParseFunctionDeclaration(NULL, ok);
1137  case Token::LET:
1138  case Token::CONST:
1139  return ParseVariableStatement(kModuleElement, NULL, ok);
1140  case Token::IMPORT:
1141  return ParseImportDeclaration(ok);
1142  case Token::EXPORT:
1143  return ParseExportDeclaration(ok);
1144  default: {
1145  Statement* stmt = ParseStatement(labels, CHECK_OK);
1146  // Handle 'module' as a context-sensitive keyword.
1147  if (FLAG_harmony_modules &&
1148  peek() == Token::IDENTIFIER &&
1149  !scanner()->HasAnyLineTerminatorBeforeNext() &&
1150  stmt != NULL) {
1151  ExpressionStatement* estmt = stmt->AsExpressionStatement();
1152  if (estmt != NULL &&
1153  estmt->expression()->AsVariableProxy() != NULL &&
1154  estmt->expression()->AsVariableProxy()->name()->Equals(
1155  isolate()->heap()->module_string()) &&
1157  return ParseModuleDeclaration(NULL, ok);
1158  }
1159  }
1160  return stmt;
1161  }
1162  }
1163 }
1164 
1165 
1166 Statement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) {
1167  // ModuleDeclaration:
1168  // 'module' Identifier Module
1169 
1170  int pos = peek_position();
1171  Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
1172 
1173 #ifdef DEBUG
1174  if (FLAG_print_interface_details)
1175  PrintF("# Module %s...\n", name->ToAsciiArray());
1176 #endif
1177 
1178  Module* module = ParseModule(CHECK_OK);
1179  VariableProxy* proxy = NewUnresolved(name, MODULE, module->interface());
1180  Declaration* declaration =
1181  factory()->NewModuleDeclaration(proxy, module, scope_, pos);
1182  Declare(declaration, true, CHECK_OK);
1183 
1184 #ifdef DEBUG
1185  if (FLAG_print_interface_details)
1186  PrintF("# Module %s.\n", name->ToAsciiArray());
1187 
1188  if (FLAG_print_interfaces) {
1189  PrintF("module %s : ", name->ToAsciiArray());
1190  module->interface()->Print();
1191  }
1192 #endif
1193 
1194  if (names) names->Add(name, zone());
1195  if (module->body() == NULL)
1196  return factory()->NewEmptyStatement(pos);
1197  else
1198  return factory()->NewModuleStatement(proxy, module->body(), pos);
1199 }
1200 
1201 
1202 Module* Parser::ParseModule(bool* ok) {
1203  // Module:
1204  // '{' ModuleElement '}'
1205  // '=' ModulePath ';'
1206  // 'at' String ';'
1207 
1208  switch (peek()) {
1209  case Token::LBRACE:
1210  return ParseModuleLiteral(ok);
1211 
1212  case Token::ASSIGN: {
1213  Expect(Token::ASSIGN, CHECK_OK);
1214  Module* result = ParseModulePath(CHECK_OK);
1216  return result;
1217  }
1218 
1219  default: {
1221  Module* result = ParseModuleUrl(CHECK_OK);
1223  return result;
1224  }
1225  }
1226 }
1227 
1228 
1229 Module* Parser::ParseModuleLiteral(bool* ok) {
1230  // Module:
1231  // '{' ModuleElement '}'
1232 
1233  int pos = peek_position();
1234  // Construct block expecting 16 statements.
1235  Block* body = factory()->NewBlock(NULL, 16, false, RelocInfo::kNoPosition);
1236 #ifdef DEBUG
1237  if (FLAG_print_interface_details) PrintF("# Literal ");
1238 #endif
1239  Scope* scope = NewScope(scope_, MODULE_SCOPE);
1240 
1241  Expect(Token::LBRACE, CHECK_OK);
1242  scope->set_start_position(scanner()->location().beg_pos);
1243  scope->SetStrictMode(STRICT);
1244 
1245  {
1246  BlockState block_state(&scope_, scope);
1247  TargetCollector collector(zone());
1248  Target target(&this->target_stack_, &collector);
1249  Target target_body(&this->target_stack_, body);
1250 
1251  while (peek() != Token::RBRACE) {
1252  Statement* stat = ParseModuleElement(NULL, CHECK_OK);
1253  if (stat && !stat->IsEmpty()) {
1254  body->AddStatement(stat, zone());
1255  }
1256  }
1257  }
1258 
1259  Expect(Token::RBRACE, CHECK_OK);
1260  scope->set_end_position(scanner()->location().end_pos);
1261  body->set_scope(scope);
1262 
1263  // Check that all exports are bound.
1264  Interface* interface = scope->interface();
1265  for (Interface::Iterator it = interface->iterator();
1266  !it.done(); it.Advance()) {
1267  if (scope->LocalLookup(it.name()) == NULL) {
1268  Handle<String> name(it.name());
1269  ParserTraits::ReportMessage("module_export_undefined",
1270  Vector<Handle<String> >(&name, 1));
1271  *ok = false;
1272  return NULL;
1273  }
1274  }
1275 
1276  interface->MakeModule(ok);
1277  ASSERT(*ok);
1278  interface->Freeze(ok);
1279  ASSERT(*ok);
1280  return factory()->NewModuleLiteral(body, interface, pos);
1281 }
1282 
1283 
1284 Module* Parser::ParseModulePath(bool* ok) {
1285  // ModulePath:
1286  // Identifier
1287  // ModulePath '.' Identifier
1288 
1289  int pos = peek_position();
1290  Module* result = ParseModuleVariable(CHECK_OK);
1291  while (Check(Token::PERIOD)) {
1292  Handle<String> name = ParseIdentifierName(CHECK_OK);
1293 #ifdef DEBUG
1294  if (FLAG_print_interface_details)
1295  PrintF("# Path .%s ", name->ToAsciiArray());
1296 #endif
1297  Module* member = factory()->NewModulePath(result, name, pos);
1298  result->interface()->Add(name, member->interface(), zone(), ok);
1299  if (!*ok) {
1300 #ifdef DEBUG
1301  if (FLAG_print_interfaces) {
1302  PrintF("PATH TYPE ERROR at '%s'\n", name->ToAsciiArray());
1303  PrintF("result: ");
1304  result->interface()->Print();
1305  PrintF("member: ");
1306  member->interface()->Print();
1307  }
1308 #endif
1309  ParserTraits::ReportMessage("invalid_module_path",
1310  Vector<Handle<String> >(&name, 1));
1311  return NULL;
1312  }
1313  result = member;
1314  }
1315 
1316  return result;
1317 }
1318 
1319 
1320 Module* Parser::ParseModuleVariable(bool* ok) {
1321  // ModulePath:
1322  // Identifier
1323 
1324  int pos = peek_position();
1325  Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
1326 #ifdef DEBUG
1327  if (FLAG_print_interface_details)
1328  PrintF("# Module variable %s ", name->ToAsciiArray());
1329 #endif
1330  VariableProxy* proxy = scope_->NewUnresolved(
1331  factory(), name, Interface::NewModule(zone()),
1332  scanner()->location().beg_pos);
1333 
1334  return factory()->NewModuleVariable(proxy, pos);
1335 }
1336 
1337 
1338 Module* Parser::ParseModuleUrl(bool* ok) {
1339  // Module:
1340  // String
1341 
1342  int pos = peek_position();
1344  Handle<String> symbol = GetSymbol();
1345 
1346  // TODO(ES6): Request JS resource from environment...
1347 
1348 #ifdef DEBUG
1349  if (FLAG_print_interface_details) PrintF("# Url ");
1350 #endif
1351 
1352  // Create an empty literal as long as the feature isn't finished.
1353  USE(symbol);
1354  Scope* scope = NewScope(scope_, MODULE_SCOPE);
1355  Block* body = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
1356  body->set_scope(scope);
1357  Interface* interface = scope->interface();
1358  Module* result = factory()->NewModuleLiteral(body, interface, pos);
1359  interface->Freeze(ok);
1360  ASSERT(*ok);
1361  interface->Unify(scope->interface(), zone(), ok);
1362  ASSERT(*ok);
1363  return result;
1364 }
1365 
1366 
1367 Module* Parser::ParseModuleSpecifier(bool* ok) {
1368  // ModuleSpecifier:
1369  // String
1370  // ModulePath
1371 
1372  if (peek() == Token::STRING) {
1373  return ParseModuleUrl(ok);
1374  } else {
1375  return ParseModulePath(ok);
1376  }
1377 }
1378 
1379 
1380 Block* Parser::ParseImportDeclaration(bool* ok) {
1381  // ImportDeclaration:
1382  // 'import' IdentifierName (',' IdentifierName)* 'from' ModuleSpecifier ';'
1383  //
1384  // TODO(ES6): implement destructuring ImportSpecifiers
1385 
1386  int pos = peek_position();
1387  Expect(Token::IMPORT, CHECK_OK);
1388  ZoneStringList names(1, zone());
1389 
1390  Handle<String> name = ParseIdentifierName(CHECK_OK);
1391  names.Add(name, zone());
1392  while (peek() == Token::COMMA) {
1394  name = ParseIdentifierName(CHECK_OK);
1395  names.Add(name, zone());
1396  }
1397 
1399  Module* module = ParseModuleSpecifier(CHECK_OK);
1401 
1402  // Generate a separate declaration for each identifier.
1403  // TODO(ES6): once we implement destructuring, make that one declaration.
1404  Block* block = factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
1405  for (int i = 0; i < names.length(); ++i) {
1406 #ifdef DEBUG
1407  if (FLAG_print_interface_details)
1408  PrintF("# Import %s ", names[i]->ToAsciiArray());
1409 #endif
1410  Interface* interface = Interface::NewUnknown(zone());
1411  module->interface()->Add(names[i], interface, zone(), ok);
1412  if (!*ok) {
1413 #ifdef DEBUG
1414  if (FLAG_print_interfaces) {
1415  PrintF("IMPORT TYPE ERROR at '%s'\n", names[i]->ToAsciiArray());
1416  PrintF("module: ");
1417  module->interface()->Print();
1418  }
1419 #endif
1420  ParserTraits::ReportMessage("invalid_module_path",
1421  Vector<Handle<String> >(&name, 1));
1422  return NULL;
1423  }
1424  VariableProxy* proxy = NewUnresolved(names[i], LET, interface);
1425  Declaration* declaration =
1426  factory()->NewImportDeclaration(proxy, module, scope_, pos);
1427  Declare(declaration, true, CHECK_OK);
1428  }
1429 
1430  return block;
1431 }
1432 
1433 
1434 Statement* Parser::ParseExportDeclaration(bool* ok) {
1435  // ExportDeclaration:
1436  // 'export' Identifier (',' Identifier)* ';'
1437  // 'export' VariableDeclaration
1438  // 'export' FunctionDeclaration
1439  // 'export' GeneratorDeclaration
1440  // 'export' ModuleDeclaration
1441  //
1442  // TODO(ES6): implement structuring ExportSpecifiers
1443 
1444  Expect(Token::EXPORT, CHECK_OK);
1445 
1446  Statement* result = NULL;
1447  ZoneStringList names(1, zone());
1448  switch (peek()) {
1449  case Token::IDENTIFIER: {
1450  int pos = position();
1451  Handle<String> name =
1453  // Handle 'module' as a context-sensitive keyword.
1454  if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("module"))) {
1455  names.Add(name, zone());
1456  while (peek() == Token::COMMA) {
1459  names.Add(name, zone());
1460  }
1462  result = factory()->NewEmptyStatement(pos);
1463  } else {
1464  result = ParseModuleDeclaration(&names, CHECK_OK);
1465  }
1466  break;
1467  }
1468 
1469  case Token::FUNCTION:
1470  result = ParseFunctionDeclaration(&names, CHECK_OK);
1471  break;
1472 
1473  case Token::VAR:
1474  case Token::LET:
1475  case Token::CONST:
1476  result = ParseVariableStatement(kModuleElement, &names, CHECK_OK);
1477  break;
1478 
1479  default:
1480  *ok = false;
1481  ReportUnexpectedToken(scanner()->current_token());
1482  return NULL;
1483  }
1484 
1485  // Extract declared names into export declarations and interface.
1486  Interface* interface = scope_->interface();
1487  for (int i = 0; i < names.length(); ++i) {
1488 #ifdef DEBUG
1489  if (FLAG_print_interface_details)
1490  PrintF("# Export %s ", names[i]->ToAsciiArray());
1491 #endif
1492  Interface* inner = Interface::NewUnknown(zone());
1493  interface->Add(names[i], inner, zone(), CHECK_OK);
1494  if (!*ok)
1495  return NULL;
1496  VariableProxy* proxy = NewUnresolved(names[i], LET, inner);
1497  USE(proxy);
1498  // TODO(rossberg): Rethink whether we actually need to store export
1499  // declarations (for compilation?).
1500  // ExportDeclaration* declaration =
1501  // factory()->NewExportDeclaration(proxy, scope_, position);
1502  // scope_->AddDeclaration(declaration);
1503  }
1504 
1505  ASSERT(result != NULL);
1506  return result;
1507 }
1508 
1509 
1510 Statement* Parser::ParseBlockElement(ZoneStringList* labels,
1511  bool* ok) {
1512  // (Ecma 262 5th Edition, clause 14):
1513  // SourceElement:
1514  // Statement
1515  // FunctionDeclaration
1516  //
1517  // In harmony mode we allow additionally the following productions
1518  // BlockElement (aka SourceElement):
1519  // LetDeclaration
1520  // ConstDeclaration
1521  // GeneratorDeclaration
1522 
1523  switch (peek()) {
1524  case Token::FUNCTION:
1525  return ParseFunctionDeclaration(NULL, ok);
1526  case Token::LET:
1527  case Token::CONST:
1528  return ParseVariableStatement(kModuleElement, NULL, ok);
1529  default:
1530  return ParseStatement(labels, ok);
1531  }
1532 }
1533 
1534 
1535 Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1536  // Statement ::
1537  // Block
1538  // VariableStatement
1539  // EmptyStatement
1540  // ExpressionStatement
1541  // IfStatement
1542  // IterationStatement
1543  // ContinueStatement
1544  // BreakStatement
1545  // ReturnStatement
1546  // WithStatement
1547  // LabelledStatement
1548  // SwitchStatement
1549  // ThrowStatement
1550  // TryStatement
1551  // DebuggerStatement
1552 
1553  // Note: Since labels can only be used by 'break' and 'continue'
1554  // statements, which themselves are only valid within blocks,
1555  // iterations or 'switch' statements (i.e., BreakableStatements),
1556  // labels can be simply ignored in all other cases; except for
1557  // trivial labeled break statements 'label: break label' which is
1558  // parsed into an empty statement.
1559  switch (peek()) {
1560  case Token::LBRACE:
1561  return ParseBlock(labels, ok);
1562 
1563  case Token::CONST: // fall through
1564  case Token::LET:
1565  case Token::VAR:
1566  return ParseVariableStatement(kStatement, NULL, ok);
1567 
1568  case Token::SEMICOLON:
1569  Next();
1570  return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1571 
1572  case Token::IF:
1573  return ParseIfStatement(labels, ok);
1574 
1575  case Token::DO:
1576  return ParseDoWhileStatement(labels, ok);
1577 
1578  case Token::WHILE:
1579  return ParseWhileStatement(labels, ok);
1580 
1581  case Token::FOR:
1582  return ParseForStatement(labels, ok);
1583 
1584  case Token::CONTINUE:
1585  return ParseContinueStatement(ok);
1586 
1587  case Token::BREAK:
1588  return ParseBreakStatement(labels, ok);
1589 
1590  case Token::RETURN:
1591  return ParseReturnStatement(ok);
1592 
1593  case Token::WITH:
1594  return ParseWithStatement(labels, ok);
1595 
1596  case Token::SWITCH:
1597  return ParseSwitchStatement(labels, ok);
1598 
1599  case Token::THROW:
1600  return ParseThrowStatement(ok);
1601 
1602  case Token::TRY: {
1603  // NOTE: It is somewhat complicated to have labels on
1604  // try-statements. When breaking out of a try-finally statement,
1605  // one must take great care not to treat it as a
1606  // fall-through. It is much easier just to wrap the entire
1607  // try-statement in a statement block and put the labels there
1608  Block* result =
1609  factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
1610  Target target(&this->target_stack_, result);
1611  TryStatement* statement = ParseTryStatement(CHECK_OK);
1612  if (result) result->AddStatement(statement, zone());
1613  return result;
1614  }
1615 
1616  case Token::FUNCTION: {
1617  // FunctionDeclaration is only allowed in the context of SourceElements
1618  // (Ecma 262 5th Edition, clause 14):
1619  // SourceElement:
1620  // Statement
1621  // FunctionDeclaration
1622  // Common language extension is to allow function declaration in place
1623  // of any statement. This language extension is disabled in strict mode.
1624  //
1625  // In Harmony mode, this case also handles the extension:
1626  // Statement:
1627  // GeneratorDeclaration
1628  if (strict_mode() == STRICT) {
1629  ReportMessageAt(scanner()->peek_location(), "strict_function");
1630  *ok = false;
1631  return NULL;
1632  }
1633  return ParseFunctionDeclaration(NULL, ok);
1634  }
1635 
1636  case Token::DEBUGGER:
1637  return ParseDebuggerStatement(ok);
1638 
1639  default:
1640  return ParseExpressionOrLabelledStatement(labels, ok);
1641  }
1642 }
1643 
1644 
1645 VariableProxy* Parser::NewUnresolved(
1646  Handle<String> name, VariableMode mode, Interface* interface) {
1647  // If we are inside a function, a declaration of a var/const variable is a
1648  // truly local variable, and the scope of the variable is always the function
1649  // scope.
1650  // Let/const variables in harmony mode are always added to the immediately
1651  // enclosing scope.
1652  return DeclarationScope(mode)->NewUnresolved(
1653  factory(), name, interface, position());
1654 }
1655 
1656 
1657 void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
1658  VariableProxy* proxy = declaration->proxy();
1659  Handle<String> name = proxy->name();
1660  VariableMode mode = declaration->mode();
1661  Scope* declaration_scope = DeclarationScope(mode);
1662  Variable* var = NULL;
1663 
1664  // If a suitable scope exists, then we can statically declare this
1665  // variable and also set its mode. In any case, a Declaration node
1666  // will be added to the scope so that the declaration can be added
1667  // to the corresponding activation frame at runtime if necessary.
1668  // For instance declarations inside an eval scope need to be added
1669  // to the calling function context.
1670  // Similarly, strict mode eval scope does not leak variable declarations to
1671  // the caller's scope so we declare all locals, too.
1672  if (declaration_scope->is_function_scope() ||
1673  declaration_scope->is_strict_eval_scope() ||
1674  declaration_scope->is_block_scope() ||
1675  declaration_scope->is_module_scope() ||
1676  declaration_scope->is_global_scope()) {
1677  // Declare the variable in the declaration scope.
1678  // For the global scope, we have to check for collisions with earlier
1679  // (i.e., enclosing) global scopes, to maintain the illusion of a single
1680  // global scope.
1681  var = declaration_scope->is_global_scope()
1682  ? declaration_scope->Lookup(name)
1683  : declaration_scope->LocalLookup(name);
1684  if (var == NULL) {
1685  // Declare the name.
1686  var = declaration_scope->DeclareLocal(
1687  name, mode, declaration->initialization(), proxy->interface());
1688  } else if ((mode != VAR || var->mode() != VAR) &&
1689  (!declaration_scope->is_global_scope() ||
1690  IsLexicalVariableMode(mode) ||
1691  IsLexicalVariableMode(var->mode()))) {
1692  // The name was declared in this scope before; check for conflicting
1693  // re-declarations. We have a conflict if either of the declarations is
1694  // not a var (in the global scope, we also have to ignore legacy const for
1695  // compatibility). There is similar code in runtime.cc in the Declare
1696  // functions. The function CheckNonConflictingScope checks for conflicting
1697  // var and let bindings from different scopes whereas this is a check for
1698  // conflicting declarations within the same scope. This check also covers
1699  // the special case
1700  //
1701  // function () { let x; { var x; } }
1702  //
1703  // because the var declaration is hoisted to the function scope where 'x'
1704  // is already bound.
1705  ASSERT(IsDeclaredVariableMode(var->mode()));
1706  if (allow_harmony_scoping() && strict_mode() == STRICT) {
1707  // In harmony we treat re-declarations as early errors. See
1708  // ES5 16 for a definition of early errors.
1709  SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
1710  const char* elms[2] = { "Variable", c_string.get() };
1711  Vector<const char*> args(elms, 2);
1712  ReportMessage("redeclaration", args);
1713  *ok = false;
1714  return;
1715  }
1716  Handle<String> message_string =
1717  isolate()->factory()->InternalizeOneByteString(
1718  STATIC_ASCII_VECTOR("Variable"));
1719  Expression* expression =
1720  NewThrowTypeError(isolate()->factory()->redeclaration_string(),
1721  message_string, name);
1722  declaration_scope->SetIllegalRedeclaration(expression);
1723  }
1724  }
1725 
1726  // We add a declaration node for every declaration. The compiler
1727  // will only generate code if necessary. In particular, declarations
1728  // for inner local variables that do not represent functions won't
1729  // result in any generated code.
1730  //
1731  // Note that we always add an unresolved proxy even if it's not
1732  // used, simply because we don't know in this method (w/o extra
1733  // parameters) if the proxy is needed or not. The proxy will be
1734  // bound during variable resolution time unless it was pre-bound
1735  // below.
1736  //
1737  // WARNING: This will lead to multiple declaration nodes for the
1738  // same variable if it is declared several times. This is not a
1739  // semantic issue as long as we keep the source order, but it may be
1740  // a performance issue since it may lead to repeated
1741  // RuntimeHidden_DeclareContextSlot calls.
1742  declaration_scope->AddDeclaration(declaration);
1743 
1744  if (mode == CONST_LEGACY && declaration_scope->is_global_scope()) {
1745  // For global const variables we bind the proxy to a variable.
1746  ASSERT(resolve); // should be set by all callers
1748  var = new(zone()) Variable(
1749  declaration_scope, name, mode, true, kind,
1750  kNeedsInitialization, proxy->interface());
1751  } else if (declaration_scope->is_eval_scope() &&
1752  declaration_scope->strict_mode() == SLOPPY) {
1753  // For variable declarations in a sloppy eval scope the proxy is bound
1754  // to a lookup variable to force a dynamic declaration using the
1755  // DeclareContextSlot runtime function.
1757  var = new(zone()) Variable(
1758  declaration_scope, name, mode, true, kind,
1759  declaration->initialization(), proxy->interface());
1760  var->AllocateTo(Variable::LOOKUP, -1);
1761  resolve = true;
1762  }
1763 
1764  // If requested and we have a local variable, bind the proxy to the variable
1765  // at parse-time. This is used for functions (and consts) declared inside
1766  // statements: the corresponding function (or const) variable must be in the
1767  // function scope and not a statement-local scope, e.g. as provided with a
1768  // 'with' statement:
1769  //
1770  // with (obj) {
1771  // function f() {}
1772  // }
1773  //
1774  // which is translated into:
1775  //
1776  // with (obj) {
1777  // // in this case this is not: 'var f; f = function () {};'
1778  // var f = function () {};
1779  // }
1780  //
1781  // Note that if 'f' is accessed from inside the 'with' statement, it
1782  // will be allocated in the context (because we must be able to look
1783  // it up dynamically) but it will also be accessed statically, i.e.,
1784  // with a context slot index and a context chain length for this
1785  // initialization code. Thus, inside the 'with' statement, we need
1786  // both access to the static and the dynamic context chain; the
1787  // runtime needs to provide both.
1788  if (resolve && var != NULL) {
1789  proxy->BindTo(var);
1790 
1791  if (FLAG_harmony_modules) {
1792  bool ok;
1793 #ifdef DEBUG
1794  if (FLAG_print_interface_details)
1795  PrintF("# Declare %s\n", var->name()->ToAsciiArray());
1796 #endif
1797  proxy->interface()->Unify(var->interface(), zone(), &ok);
1798  if (!ok) {
1799 #ifdef DEBUG
1800  if (FLAG_print_interfaces) {
1801  PrintF("DECLARE TYPE ERROR\n");
1802  PrintF("proxy: ");
1803  proxy->interface()->Print();
1804  PrintF("var: ");
1805  var->interface()->Print();
1806  }
1807 #endif
1808  ParserTraits::ReportMessage("module_type_error",
1809  Vector<Handle<String> >(&name, 1));
1810  }
1811  }
1812  }
1813 }
1814 
1815 
1816 // Language extension which is only enabled for source files loaded
1817 // through the API's extension mechanism. A native function
1818 // declaration is resolved by looking up the function through a
1819 // callback provided by the extension.
1820 Statement* Parser::ParseNativeDeclaration(bool* ok) {
1821  int pos = peek_position();
1822  Expect(Token::FUNCTION, CHECK_OK);
1823  // Allow "eval" or "arguments" for backward compatibility.
1824  Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
1825  Expect(Token::LPAREN, CHECK_OK);
1826  bool done = (peek() == Token::RPAREN);
1827  while (!done) {
1829  done = (peek() == Token::RPAREN);
1830  if (!done) {
1832  }
1833  }
1834  Expect(Token::RPAREN, CHECK_OK);
1835  Expect(Token::SEMICOLON, CHECK_OK);
1836 
1837  // Make sure that the function containing the native declaration
1838  // isn't lazily compiled. The extension structures are only
1839  // accessible while parsing the first time not when reparsing
1840  // because of lazy compilation.
1841  DeclarationScope(VAR)->ForceEagerCompilation();
1842 
1843  // TODO(1240846): It's weird that native function declarations are
1844  // introduced dynamically when we meet their declarations, whereas
1845  // other functions are set up when entering the surrounding scope.
1846  VariableProxy* proxy = NewUnresolved(name, VAR, Interface::NewValue());
1847  Declaration* declaration =
1848  factory()->NewVariableDeclaration(proxy, VAR, scope_, pos);
1849  Declare(declaration, true, CHECK_OK);
1850  NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
1851  name, extension_, RelocInfo::kNoPosition);
1852  return factory()->NewExpressionStatement(
1853  factory()->NewAssignment(
1854  Token::INIT_VAR, proxy, lit, RelocInfo::kNoPosition),
1855  pos);
1856 }
1857 
1858 
1859 Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
1860  // FunctionDeclaration ::
1861  // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1862  // GeneratorDeclaration ::
1863  // 'function' '*' Identifier '(' FormalParameterListopt ')'
1864  // '{' FunctionBody '}'
1865  Expect(Token::FUNCTION, CHECK_OK);
1866  int pos = position();
1868  bool is_strict_reserved = false;
1869  Handle<String> name = ParseIdentifierOrStrictReservedWord(
1870  &is_strict_reserved, CHECK_OK);
1871  FunctionLiteral* fun = ParseFunctionLiteral(name,
1872  scanner()->location(),
1873  is_strict_reserved,
1874  is_generator,
1875  pos,
1876  FunctionLiteral::DECLARATION,
1877  CHECK_OK);
1878  // Even if we're not at the top-level of the global or a function
1879  // scope, we treat it as such and introduce the function with its
1880  // initial value upon entering the corresponding scope.
1881  // In extended mode, a function behaves as a lexical binding, except in the
1882  // global scope.
1883  VariableMode mode =
1885  strict_mode() == STRICT && !scope_->is_global_scope() ? LET : VAR;
1886  VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
1887  Declaration* declaration =
1888  factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
1889  Declare(declaration, true, CHECK_OK);
1890  if (names) names->Add(name, zone());
1891  return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1892 }
1893 
1894 
1895 Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
1896  if (allow_harmony_scoping() && strict_mode() == STRICT) {
1897  return ParseScopedBlock(labels, ok);
1898  }
1899 
1900  // Block ::
1901  // '{' Statement* '}'
1902 
1903  // Note that a Block does not introduce a new execution scope!
1904  // (ECMA-262, 3rd, 12.2)
1905  //
1906  // Construct block expecting 16 statements.
1907  Block* result =
1908  factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
1909  Target target(&this->target_stack_, result);
1910  Expect(Token::LBRACE, CHECK_OK);
1911  while (peek() != Token::RBRACE) {
1912  Statement* stat = ParseStatement(NULL, CHECK_OK);
1913  if (stat && !stat->IsEmpty()) {
1914  result->AddStatement(stat, zone());
1915  }
1916  }
1917  Expect(Token::RBRACE, CHECK_OK);
1918  return result;
1919 }
1920 
1921 
1922 Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
1923  // The harmony mode uses block elements instead of statements.
1924  //
1925  // Block ::
1926  // '{' BlockElement* '}'
1927 
1928  // Construct block expecting 16 statements.
1929  Block* body =
1930  factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
1931  Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
1932 
1933  // Parse the statements and collect escaping labels.
1934  Expect(Token::LBRACE, CHECK_OK);
1935  block_scope->set_start_position(scanner()->location().beg_pos);
1936  { BlockState block_state(&scope_, block_scope);
1937  TargetCollector collector(zone());
1938  Target target(&this->target_stack_, &collector);
1939  Target target_body(&this->target_stack_, body);
1940 
1941  while (peek() != Token::RBRACE) {
1942  Statement* stat = ParseBlockElement(NULL, CHECK_OK);
1943  if (stat && !stat->IsEmpty()) {
1944  body->AddStatement(stat, zone());
1945  }
1946  }
1947  }
1948  Expect(Token::RBRACE, CHECK_OK);
1949  block_scope->set_end_position(scanner()->location().end_pos);
1950  block_scope = block_scope->FinalizeBlockScope();
1951  body->set_scope(block_scope);
1952  return body;
1953 }
1954 
1955 
1956 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
1957  ZoneStringList* names,
1958  bool* ok) {
1959  // VariableStatement ::
1960  // VariableDeclarations ';'
1961 
1962  Handle<String> ignore;
1963  Block* result =
1964  ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK);
1966  return result;
1967 }
1968 
1969 
1970 // If the variable declaration declares exactly one non-const
1971 // variable, then *out is set to that variable. In all other cases,
1972 // *out is untouched; in particular, it is the caller's responsibility
1973 // to initialize it properly. This mechanism is used for the parsing
1974 // of 'for-in' loops.
1975 Block* Parser::ParseVariableDeclarations(
1976  VariableDeclarationContext var_context,
1977  VariableDeclarationProperties* decl_props,
1978  ZoneStringList* names,
1979  Handle<String>* out,
1980  bool* ok) {
1981  // VariableDeclarations ::
1982  // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
1983  //
1984  // The ES6 Draft Rev3 specifies the following grammar for const declarations
1985  //
1986  // ConstDeclaration ::
1987  // const ConstBinding (',' ConstBinding)* ';'
1988  // ConstBinding ::
1989  // Identifier '=' AssignmentExpression
1990  //
1991  // TODO(ES6):
1992  // ConstBinding ::
1993  // BindingPattern '=' AssignmentExpression
1994 
1995  int pos = peek_position();
1996  VariableMode mode = VAR;
1997  // True if the binding needs initialization. 'let' and 'const' declared
1998  // bindings are created uninitialized by their declaration nodes and
1999  // need initialization. 'var' declared bindings are always initialized
2000  // immediately by their declaration nodes.
2001  bool needs_init = false;
2002  bool is_const = false;
2003  Token::Value init_op = Token::INIT_VAR;
2004  if (peek() == Token::VAR) {
2006  } else if (peek() == Token::CONST) {
2007  // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
2008  //
2009  // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
2010  //
2011  // * It is a Syntax Error if the code that matches this production is not
2012  // contained in extended code.
2013  //
2014  // However disallowing const in sloppy mode will break compatibility with
2015  // existing pages. Therefore we keep allowing const with the old
2016  // non-harmony semantics in sloppy mode.
2018  switch (strict_mode()) {
2019  case SLOPPY:
2020  mode = CONST_LEGACY;
2021  init_op = Token::INIT_CONST_LEGACY;
2022  break;
2023  case STRICT:
2024  if (allow_harmony_scoping()) {
2025  if (var_context == kStatement) {
2026  // In strict mode 'const' declarations are only allowed in source
2027  // element positions.
2028  ReportMessage("unprotected_const", Vector<const char*>::empty());
2029  *ok = false;
2030  return NULL;
2031  }
2032  mode = CONST;
2033  init_op = Token::INIT_CONST;
2034  } else {
2035  ReportMessage("strict_const", Vector<const char*>::empty());
2036  *ok = false;
2037  return NULL;
2038  }
2039  }
2040  is_const = true;
2041  needs_init = true;
2042  } else if (peek() == Token::LET) {
2043  // ES6 Draft Rev4 section 12.2.1:
2044  //
2045  // LetDeclaration : let LetBindingList ;
2046  //
2047  // * It is a Syntax Error if the code that matches this production is not
2048  // contained in extended code.
2049  //
2050  // TODO(rossberg): make 'let' a legal identifier in sloppy mode.
2051  if (!allow_harmony_scoping() || strict_mode() == SLOPPY) {
2052  ReportMessage("illegal_let", Vector<const char*>::empty());
2053  *ok = false;
2054  return NULL;
2055  }
2057  if (var_context == kStatement) {
2058  // Let declarations are only allowed in source element positions.
2059  ReportMessage("unprotected_let", Vector<const char*>::empty());
2060  *ok = false;
2061  return NULL;
2062  }
2063  mode = LET;
2064  needs_init = true;
2065  init_op = Token::INIT_LET;
2066  } else {
2067  UNREACHABLE(); // by current callers
2068  }
2069 
2070  Scope* declaration_scope = DeclarationScope(mode);
2071 
2072  // The scope of a var/const declared variable anywhere inside a function
2073  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
2074  // transform a source-level var/const declaration into a (Function)
2075  // Scope declaration, and rewrite the source-level initialization into an
2076  // assignment statement. We use a block to collect multiple assignments.
2077  //
2078  // We mark the block as initializer block because we don't want the
2079  // rewriter to add a '.result' assignment to such a block (to get compliant
2080  // behavior for code such as print(eval('var x = 7')), and for cosmetic
2081  // reasons when pretty-printing. Also, unless an assignment (initialization)
2082  // is inside an initializer block, it is ignored.
2083  //
2084  // Create new block with one expected declaration.
2085  Block* block = factory()->NewBlock(NULL, 1, true, pos);
2086  int nvars = 0; // the number of variables declared
2087  Handle<String> name;
2088  do {
2089  if (fni_ != NULL) fni_->Enter();
2090 
2091  // Parse variable name.
2092  if (nvars > 0) Consume(Token::COMMA);
2094  if (fni_ != NULL) fni_->PushVariableName(name);
2095 
2096  // Declare variable.
2097  // Note that we *always* must treat the initial value via a separate init
2098  // assignment for variables and constants because the value must be assigned
2099  // when the variable is encountered in the source. But the variable/constant
2100  // is declared (and set to 'undefined') upon entering the function within
2101  // which the variable or constant is declared. Only function variables have
2102  // an initial value in the declaration (because they are initialized upon
2103  // entering the function).
2104  //
2105  // If we have a const declaration, in an inner scope, the proxy is always
2106  // bound to the declared variable (independent of possibly surrounding with
2107  // statements).
2108  // For let/const declarations in harmony mode, we can also immediately
2109  // pre-resolve the proxy because it resides in the same scope as the
2110  // declaration.
2111  Interface* interface =
2112  is_const ? Interface::NewConst() : Interface::NewValue();
2113  VariableProxy* proxy = NewUnresolved(name, mode, interface);
2114  Declaration* declaration =
2115  factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
2116  Declare(declaration, mode != VAR, CHECK_OK);
2117  nvars++;
2118  if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
2119  ReportMessageAt(scanner()->location(), "too_many_variables");
2120  *ok = false;
2121  return NULL;
2122  }
2123  if (names) names->Add(name, zone());
2124 
2125  // Parse initialization expression if present and/or needed. A
2126  // declaration of the form:
2127  //
2128  // var v = x;
2129  //
2130  // is syntactic sugar for:
2131  //
2132  // var v; v = x;
2133  //
2134  // In particular, we need to re-lookup 'v' (in scope_, not
2135  // declaration_scope) as it may be a different 'v' than the 'v' in the
2136  // declaration (e.g., if we are inside a 'with' statement or 'catch'
2137  // block).
2138  //
2139  // However, note that const declarations are different! A const
2140  // declaration of the form:
2141  //
2142  // const c = x;
2143  //
2144  // is *not* syntactic sugar for:
2145  //
2146  // const c; c = x;
2147  //
2148  // The "variable" c initialized to x is the same as the declared
2149  // one - there is no re-lookup (see the last parameter of the
2150  // Declare() call above).
2151 
2152  Scope* initialization_scope = is_const ? declaration_scope : scope_;
2153  Expression* value = NULL;
2154  int pos = -1;
2155  // Harmony consts have non-optional initializers.
2156  if (peek() == Token::ASSIGN || mode == CONST) {
2157  Expect(Token::ASSIGN, CHECK_OK);
2158  pos = position();
2159  value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
2160  // Don't infer if it is "a = function(){...}();"-like expression.
2161  if (fni_ != NULL &&
2162  value->AsCall() == NULL &&
2163  value->AsCallNew() == NULL) {
2164  fni_->Infer();
2165  } else {
2167  }
2168  if (decl_props != NULL) *decl_props = kHasInitializers;
2169  }
2170 
2171  // Record the end position of the initializer.
2172  if (proxy->var() != NULL) {
2173  proxy->var()->set_initializer_position(position());
2174  }
2175 
2176  // Make sure that 'const x' and 'let x' initialize 'x' to undefined.
2177  if (value == NULL && needs_init) {
2178  value = GetLiteralUndefined(position());
2179  }
2180 
2181  // Global variable declarations must be compiled in a specific
2182  // way. When the script containing the global variable declaration
2183  // is entered, the global variable must be declared, so that if it
2184  // doesn't exist (on the global object itself, see ES5 errata) it
2185  // gets created with an initial undefined value. This is handled
2186  // by the declarations part of the function representing the
2187  // top-level global code; see Runtime::DeclareGlobalVariable. If
2188  // it already exists (in the object or in a prototype), it is
2189  // *not* touched until the variable declaration statement is
2190  // executed.
2191  //
2192  // Executing the variable declaration statement will always
2193  // guarantee to give the global object a "local" variable; a
2194  // variable defined in the global object and not in any
2195  // prototype. This way, global variable declarations can shadow
2196  // properties in the prototype chain, but only after the variable
2197  // declaration statement has been executed. This is important in
2198  // browsers where the global object (window) has lots of
2199  // properties defined in prototype objects.
2200  if (initialization_scope->is_global_scope() &&
2201  !IsLexicalVariableMode(mode)) {
2202  // Compute the arguments for the runtime call.
2203  ZoneList<Expression*>* arguments =
2204  new(zone()) ZoneList<Expression*>(3, zone());
2205  // We have at least 1 parameter.
2206  arguments->Add(factory()->NewLiteral(name, pos), zone());
2207  CallRuntime* initialize;
2208 
2209  if (is_const) {
2210  arguments->Add(value, zone());
2211  value = NULL; // zap the value to avoid the unnecessary assignment
2212 
2213  // Construct the call to Runtime_InitializeConstGlobal
2214  // and add it to the initialization statement block.
2215  // Note that the function does different things depending on
2216  // the number of arguments (1 or 2).
2217  initialize = factory()->NewCallRuntime(
2218  isolate()->factory()->InitializeConstGlobal_string(),
2219  Runtime::FunctionForId(Runtime::kHiddenInitializeConstGlobal),
2220  arguments, pos);
2221  } else {
2222  // Add strict mode.
2223  // We may want to pass singleton to avoid Literal allocations.
2224  StrictMode strict_mode = initialization_scope->strict_mode();
2225  arguments->Add(factory()->NewNumberLiteral(strict_mode, pos), zone());
2226 
2227  // Be careful not to assign a value to the global variable if
2228  // we're in a with. The initialization value should not
2229  // necessarily be stored in the global object in that case,
2230  // which is why we need to generate a separate assignment node.
2231  if (value != NULL && !inside_with()) {
2232  arguments->Add(value, zone());
2233  value = NULL; // zap the value to avoid the unnecessary assignment
2234  }
2235 
2236  // Construct the call to Runtime_InitializeVarGlobal
2237  // and add it to the initialization statement block.
2238  // Note that the function does different things depending on
2239  // the number of arguments (2 or 3).
2240  initialize = factory()->NewCallRuntime(
2241  isolate()->factory()->InitializeVarGlobal_string(),
2242  Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
2243  arguments, pos);
2244  }
2245 
2246  block->AddStatement(
2247  factory()->NewExpressionStatement(initialize, RelocInfo::kNoPosition),
2248  zone());
2249  } else if (needs_init) {
2250  // Constant initializations always assign to the declared constant which
2251  // is always at the function scope level. This is only relevant for
2252  // dynamically looked-up variables and constants (the start context for
2253  // constant lookups is always the function context, while it is the top
2254  // context for var declared variables). Sigh...
2255  // For 'let' and 'const' declared variables in harmony mode the
2256  // initialization also always assigns to the declared variable.
2257  ASSERT(proxy != NULL);
2258  ASSERT(proxy->var() != NULL);
2259  ASSERT(value != NULL);
2260  Assignment* assignment =
2261  factory()->NewAssignment(init_op, proxy, value, pos);
2262  block->AddStatement(
2263  factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
2264  zone());
2265  value = NULL;
2266  }
2267 
2268  // Add an assignment node to the initialization statement block if we still
2269  // have a pending initialization value.
2270  if (value != NULL) {
2271  ASSERT(mode == VAR);
2272  // 'var' initializations are simply assignments (with all the consequences
2273  // if they are inside a 'with' statement - they may change a 'with' object
2274  // property).
2275  VariableProxy* proxy =
2276  initialization_scope->NewUnresolved(factory(), name, interface);
2277  Assignment* assignment =
2278  factory()->NewAssignment(init_op, proxy, value, pos);
2279  block->AddStatement(
2280  factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
2281  zone());
2282  }
2283 
2284  if (fni_ != NULL) fni_->Leave();
2285  } while (peek() == Token::COMMA);
2286 
2287  // If there was a single non-const declaration, return it in the output
2288  // parameter for possible use by for/in.
2289  if (nvars == 1 && !is_const) {
2290  *out = name;
2291  }
2292 
2293  return block;
2294 }
2295 
2296 
2297 static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
2298  ASSERT(!label.is_null());
2299  if (labels != NULL)
2300  for (int i = labels->length(); i-- > 0; )
2301  if (labels->at(i).is_identical_to(label))
2302  return true;
2303 
2304  return false;
2305 }
2306 
2307 
2308 Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
2309  bool* ok) {
2310  // ExpressionStatement | LabelledStatement ::
2311  // Expression ';'
2312  // Identifier ':' Statement
2313  int pos = peek_position();
2314  bool starts_with_idenfifier = peek_any_identifier();
2315  Expression* expr = ParseExpression(true, CHECK_OK);
2316  if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
2317  expr->AsVariableProxy() != NULL &&
2318  !expr->AsVariableProxy()->is_this()) {
2319  // Expression is a single identifier, and not, e.g., a parenthesized
2320  // identifier.
2321  VariableProxy* var = expr->AsVariableProxy();
2322  Handle<String> label = var->name();
2323  // TODO(1240780): We don't check for redeclaration of labels
2324  // during preparsing since keeping track of the set of active
2325  // labels requires nontrivial changes to the way scopes are
2326  // structured. However, these are probably changes we want to
2327  // make later anyway so we should go back and fix this then.
2328  if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
2329  SmartArrayPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
2330  const char* elms[2] = { "Label", c_string.get() };
2331  Vector<const char*> args(elms, 2);
2332  ReportMessage("redeclaration", args);
2333  *ok = false;
2334  return NULL;
2335  }
2336  if (labels == NULL) {
2337  labels = new(zone()) ZoneStringList(4, zone());
2338  }
2339  labels->Add(label, zone());
2340  // Remove the "ghost" variable that turned out to be a label
2341  // from the top scope. This way, we don't try to resolve it
2342  // during the scope processing.
2343  scope_->RemoveUnresolved(var);
2344  Expect(Token::COLON, CHECK_OK);
2345  return ParseStatement(labels, ok);
2346  }
2347 
2348  // If we have an extension, we allow a native function declaration.
2349  // A native function declaration starts with "native function" with
2350  // no line-terminator between the two words.
2351  if (extension_ != NULL &&
2352  peek() == Token::FUNCTION &&
2353  !scanner()->HasAnyLineTerminatorBeforeNext() &&
2354  expr != NULL &&
2355  expr->AsVariableProxy() != NULL &&
2356  expr->AsVariableProxy()->name()->Equals(
2357  isolate()->heap()->native_string()) &&
2359  return ParseNativeDeclaration(ok);
2360  }
2361 
2362  // Parsed expression statement, or the context-sensitive 'module' keyword.
2363  // Only expect semicolon in the former case.
2364  if (!FLAG_harmony_modules ||
2365  peek() != Token::IDENTIFIER ||
2366  scanner()->HasAnyLineTerminatorBeforeNext() ||
2367  expr->AsVariableProxy() == NULL ||
2368  !expr->AsVariableProxy()->name()->Equals(
2369  isolate()->heap()->module_string()) ||
2372  }
2373  return factory()->NewExpressionStatement(expr, pos);
2374 }
2375 
2376 
2377 IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
2378  // IfStatement ::
2379  // 'if' '(' Expression ')' Statement ('else' Statement)?
2380 
2381  int pos = peek_position();
2382  Expect(Token::IF, CHECK_OK);
2383  Expect(Token::LPAREN, CHECK_OK);
2384  Expression* condition = ParseExpression(true, CHECK_OK);
2385  Expect(Token::RPAREN, CHECK_OK);
2386  Statement* then_statement = ParseStatement(labels, CHECK_OK);
2387  Statement* else_statement = NULL;
2388  if (peek() == Token::ELSE) {
2389  Next();
2390  else_statement = ParseStatement(labels, CHECK_OK);
2391  } else {
2392  else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
2393  }
2394  return factory()->NewIfStatement(
2395  condition, then_statement, else_statement, pos);
2396 }
2397 
2398 
2399 Statement* Parser::ParseContinueStatement(bool* ok) {
2400  // ContinueStatement ::
2401  // 'continue' Identifier? ';'
2402 
2403  int pos = peek_position();
2404  Expect(Token::CONTINUE, CHECK_OK);
2405  Handle<String> label = Handle<String>::null();
2406  Token::Value tok = peek();
2407  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
2408  tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2409  // ECMA allows "eval" or "arguments" as labels even in strict mode.
2411  }
2412  IterationStatement* target = NULL;
2413  target = LookupContinueTarget(label, CHECK_OK);
2414  if (target == NULL) {
2415  // Illegal continue statement.
2416  const char* message = "illegal_continue";
2417  Vector<Handle<String> > args;
2418  if (!label.is_null()) {
2419  message = "unknown_label";
2420  args = Vector<Handle<String> >(&label, 1);
2421  }
2422  ParserTraits::ReportMessageAt(scanner()->location(), message, args);
2423  *ok = false;
2424  return NULL;
2425  }
2427  return factory()->NewContinueStatement(target, pos);
2428 }
2429 
2430 
2431 Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
2432  // BreakStatement ::
2433  // 'break' Identifier? ';'
2434 
2435  int pos = peek_position();
2437  Handle<String> label;
2438  Token::Value tok = peek();
2439  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
2440  tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2441  // ECMA allows "eval" or "arguments" as labels even in strict mode.
2443  }
2444  // Parse labeled break statements that target themselves into
2445  // empty statements, e.g. 'l1: l2: l3: break l2;'
2446  if (!label.is_null() && ContainsLabel(labels, label)) {
2448  return factory()->NewEmptyStatement(pos);
2449  }
2450  BreakableStatement* target = NULL;
2451  target = LookupBreakTarget(label, CHECK_OK);
2452  if (target == NULL) {
2453  // Illegal break statement.
2454  const char* message = "illegal_break";
2455  Vector<Handle<String> > args;
2456  if (!label.is_null()) {
2457  message = "unknown_label";
2458  args = Vector<Handle<String> >(&label, 1);
2459  }
2460  ParserTraits::ReportMessageAt(scanner()->location(), message, args);
2461  *ok = false;
2462  return NULL;
2463  }
2465  return factory()->NewBreakStatement(target, pos);
2466 }
2467 
2468 
2469 Statement* Parser::ParseReturnStatement(bool* ok) {
2470  // ReturnStatement ::
2471  // 'return' Expression? ';'
2472 
2473  // Consume the return token. It is necessary to do that before
2474  // reporting any errors on it, because of the way errors are
2475  // reported (underlining).
2476  Expect(Token::RETURN, CHECK_OK);
2477  int pos = position();
2478 
2479  Token::Value tok = peek();
2480  Statement* result;
2481  Expression* return_value;
2482  if (scanner()->HasAnyLineTerminatorBeforeNext() ||
2483  tok == Token::SEMICOLON ||
2484  tok == Token::RBRACE ||
2485  tok == Token::EOS) {
2486  return_value = GetLiteralUndefined(position());
2487  } else {
2488  return_value = ParseExpression(true, CHECK_OK);
2489  }
2491  if (is_generator()) {
2492  Expression* generator = factory()->NewVariableProxy(
2493  function_state_->generator_object_variable());
2494  Expression* yield = factory()->NewYield(
2495  generator, return_value, Yield::FINAL, pos);
2496  result = factory()->NewExpressionStatement(yield, pos);
2497  } else {
2498  result = factory()->NewReturnStatement(return_value, pos);
2499  }
2500 
2501  // An ECMAScript program is considered syntactically incorrect if it
2502  // contains a return statement that is not within the body of a
2503  // function. See ECMA-262, section 12.9, page 67.
2504  //
2505  // To be consistent with KJS we report the syntax error at runtime.
2506  Scope* declaration_scope = scope_->DeclarationScope();
2507  if (declaration_scope->is_global_scope() ||
2508  declaration_scope->is_eval_scope()) {
2509  Handle<String> message = isolate()->factory()->illegal_return_string();
2510  Expression* throw_error =
2511  NewThrowSyntaxError(message, Handle<Object>::null());
2512  return factory()->NewExpressionStatement(throw_error, pos);
2513  }
2514  return result;
2515 }
2516 
2517 
2518 Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
2519  // WithStatement ::
2520  // 'with' '(' Expression ')' Statement
2521 
2522  Expect(Token::WITH, CHECK_OK);
2523  int pos = position();
2524 
2525  if (strict_mode() == STRICT) {
2526  ReportMessage("strict_mode_with", Vector<const char*>::empty());
2527  *ok = false;
2528  return NULL;
2529  }
2530 
2531  Expect(Token::LPAREN, CHECK_OK);
2532  Expression* expr = ParseExpression(true, CHECK_OK);
2533  Expect(Token::RPAREN, CHECK_OK);
2534 
2535  scope_->DeclarationScope()->RecordWithStatement();
2536  Scope* with_scope = NewScope(scope_, WITH_SCOPE);
2537  Statement* stmt;
2538  { BlockState block_state(&scope_, with_scope);
2539  with_scope->set_start_position(scanner()->peek_location().beg_pos);
2540  stmt = ParseStatement(labels, CHECK_OK);
2541  with_scope->set_end_position(scanner()->location().end_pos);
2542  }
2543  return factory()->NewWithStatement(with_scope, expr, stmt, pos);
2544 }
2545 
2546 
2547 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
2548  // CaseClause ::
2549  // 'case' Expression ':' Statement*
2550  // 'default' ':' Statement*
2551 
2552  Expression* label = NULL; // NULL expression indicates default case
2553  if (peek() == Token::CASE) {
2555  label = ParseExpression(true, CHECK_OK);
2556  } else {
2558  if (*default_seen_ptr) {
2559  ReportMessage("multiple_defaults_in_switch",
2560  Vector<const char*>::empty());
2561  *ok = false;
2562  return NULL;
2563  }
2564  *default_seen_ptr = true;
2565  }
2566  Expect(Token::COLON, CHECK_OK);
2567  int pos = position();
2568  ZoneList<Statement*>* statements =
2569  new(zone()) ZoneList<Statement*>(5, zone());
2570  while (peek() != Token::CASE &&
2571  peek() != Token::DEFAULT &&
2572  peek() != Token::RBRACE) {
2573  Statement* stat = ParseStatement(NULL, CHECK_OK);
2574  statements->Add(stat, zone());
2575  }
2576 
2577  return factory()->NewCaseClause(label, statements, pos);
2578 }
2579 
2580 
2581 SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
2582  bool* ok) {
2583  // SwitchStatement ::
2584  // 'switch' '(' Expression ')' '{' CaseClause* '}'
2585 
2586  SwitchStatement* statement =
2587  factory()->NewSwitchStatement(labels, peek_position());
2588  Target target(&this->target_stack_, statement);
2589 
2590  Expect(Token::SWITCH, CHECK_OK);
2591  Expect(Token::LPAREN, CHECK_OK);
2592  Expression* tag = ParseExpression(true, CHECK_OK);
2593  Expect(Token::RPAREN, CHECK_OK);
2594 
2595  bool default_seen = false;
2596  ZoneList<CaseClause*>* cases = new(zone()) ZoneList<CaseClause*>(4, zone());
2597  Expect(Token::LBRACE, CHECK_OK);
2598  while (peek() != Token::RBRACE) {
2599  CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
2600  cases->Add(clause, zone());
2601  }
2602  Expect(Token::RBRACE, CHECK_OK);
2603 
2604  if (statement) statement->Initialize(tag, cases);
2605  return statement;
2606 }
2607 
2608 
2609 Statement* Parser::ParseThrowStatement(bool* ok) {
2610  // ThrowStatement ::
2611  // 'throw' Expression ';'
2612 
2613  Expect(Token::THROW, CHECK_OK);
2614  int pos = position();
2615  if (scanner()->HasAnyLineTerminatorBeforeNext()) {
2616  ReportMessage("newline_after_throw", Vector<const char*>::empty());
2617  *ok = false;
2618  return NULL;
2619  }
2620  Expression* exception = ParseExpression(true, CHECK_OK);
2622 
2623  return factory()->NewExpressionStatement(
2624  factory()->NewThrow(exception, pos), pos);
2625 }
2626 
2627 
2628 TryStatement* Parser::ParseTryStatement(bool* ok) {
2629  // TryStatement ::
2630  // 'try' Block Catch
2631  // 'try' Block Finally
2632  // 'try' Block Catch Finally
2633  //
2634  // Catch ::
2635  // 'catch' '(' Identifier ')' Block
2636  //
2637  // Finally ::
2638  // 'finally' Block
2639 
2640  Expect(Token::TRY, CHECK_OK);
2641  int pos = position();
2642 
2643  TargetCollector try_collector(zone());
2644  Block* try_block;
2645 
2646  { Target target(&this->target_stack_, &try_collector);
2647  try_block = ParseBlock(NULL, CHECK_OK);
2648  }
2649 
2650  Token::Value tok = peek();
2651  if (tok != Token::CATCH && tok != Token::FINALLY) {
2652  ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
2653  *ok = false;
2654  return NULL;
2655  }
2656 
2657  // If we can break out from the catch block and there is a finally block,
2658  // then we will need to collect escaping targets from the catch
2659  // block. Since we don't know yet if there will be a finally block, we
2660  // always collect the targets.
2661  TargetCollector catch_collector(zone());
2662  Scope* catch_scope = NULL;
2663  Variable* catch_variable = NULL;
2664  Block* catch_block = NULL;
2665  Handle<String> name;
2666  if (tok == Token::CATCH) {
2667  Consume(Token::CATCH);
2668 
2669  Expect(Token::LPAREN, CHECK_OK);
2670  catch_scope = NewScope(scope_, CATCH_SCOPE);
2671  catch_scope->set_start_position(scanner()->location().beg_pos);
2673 
2674  Expect(Token::RPAREN, CHECK_OK);
2675 
2676  Target target(&this->target_stack_, &catch_collector);
2677  VariableMode mode =
2679  catch_variable =
2680  catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
2681 
2682  BlockState block_state(&scope_, catch_scope);
2683  catch_block = ParseBlock(NULL, CHECK_OK);
2684 
2685  catch_scope->set_end_position(scanner()->location().end_pos);
2686  tok = peek();
2687  }
2688 
2689  Block* finally_block = NULL;
2690  ASSERT(tok == Token::FINALLY || catch_block != NULL);
2691  if (tok == Token::FINALLY) {
2692  Consume(Token::FINALLY);
2693  finally_block = ParseBlock(NULL, CHECK_OK);
2694  }
2695 
2696  // Simplify the AST nodes by converting:
2697  // 'try B0 catch B1 finally B2'
2698  // to:
2699  // 'try { try B0 catch B1 } finally B2'
2700 
2701  if (catch_block != NULL && finally_block != NULL) {
2702  // If we have both, create an inner try/catch.
2703  ASSERT(catch_scope != NULL && catch_variable != NULL);
2704  int index = function_state_->NextHandlerIndex();
2705  TryCatchStatement* statement = factory()->NewTryCatchStatement(
2706  index, try_block, catch_scope, catch_variable, catch_block,
2707  RelocInfo::kNoPosition);
2708  statement->set_escaping_targets(try_collector.targets());
2709  try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
2710  try_block->AddStatement(statement, zone());
2711  catch_block = NULL; // Clear to indicate it's been handled.
2712  }
2713 
2714  TryStatement* result = NULL;
2715  if (catch_block != NULL) {
2716  ASSERT(finally_block == NULL);
2717  ASSERT(catch_scope != NULL && catch_variable != NULL);
2718  int index = function_state_->NextHandlerIndex();
2719  result = factory()->NewTryCatchStatement(
2720  index, try_block, catch_scope, catch_variable, catch_block, pos);
2721  } else {
2722  ASSERT(finally_block != NULL);
2723  int index = function_state_->NextHandlerIndex();
2724  result = factory()->NewTryFinallyStatement(
2725  index, try_block, finally_block, pos);
2726  // Combine the jump targets of the try block and the possible catch block.
2727  try_collector.targets()->AddAll(*catch_collector.targets(), zone());
2728  }
2729 
2730  result->set_escaping_targets(try_collector.targets());
2731  return result;
2732 }
2733 
2734 
2735 DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
2736  bool* ok) {
2737  // DoStatement ::
2738  // 'do' Statement 'while' '(' Expression ')' ';'
2739 
2740  DoWhileStatement* loop =
2741  factory()->NewDoWhileStatement(labels, peek_position());
2742  Target target(&this->target_stack_, loop);
2743 
2744  Expect(Token::DO, CHECK_OK);
2745  Statement* body = ParseStatement(NULL, CHECK_OK);
2746  Expect(Token::WHILE, CHECK_OK);
2747  Expect(Token::LPAREN, CHECK_OK);
2748 
2749  Expression* cond = ParseExpression(true, CHECK_OK);
2750  Expect(Token::RPAREN, CHECK_OK);
2751 
2752  // Allow do-statements to be terminated with and without
2753  // semi-colons. This allows code such as 'do;while(0)return' to
2754  // parse, which would not be the case if we had used the
2755  // ExpectSemicolon() functionality here.
2756  if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2757 
2758  if (loop != NULL) loop->Initialize(cond, body);
2759  return loop;
2760 }
2761 
2762 
2763 WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
2764  // WhileStatement ::
2765  // 'while' '(' Expression ')' Statement
2766 
2767  WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
2768  Target target(&this->target_stack_, loop);
2769 
2770  Expect(Token::WHILE, CHECK_OK);
2771  Expect(Token::LPAREN, CHECK_OK);
2772  Expression* cond = ParseExpression(true, CHECK_OK);
2773  Expect(Token::RPAREN, CHECK_OK);
2774  Statement* body = ParseStatement(NULL, CHECK_OK);
2775 
2776  if (loop != NULL) loop->Initialize(cond, body);
2777  return loop;
2778 }
2779 
2780 
2781 bool Parser::CheckInOrOf(bool accept_OF,
2782  ForEachStatement::VisitMode* visit_mode) {
2783  if (Check(Token::IN)) {
2784  *visit_mode = ForEachStatement::ENUMERATE;
2785  return true;
2786  } else if (allow_for_of() && accept_OF &&
2788  *visit_mode = ForEachStatement::ITERATE;
2789  return true;
2790  }
2791  return false;
2792 }
2793 
2794 
2795 void Parser::InitializeForEachStatement(ForEachStatement* stmt,
2796  Expression* each,
2797  Expression* subject,
2798  Statement* body) {
2799  ForOfStatement* for_of = stmt->AsForOfStatement();
2800 
2801  if (for_of != NULL) {
2802  Factory* heap_factory = isolate()->factory();
2803  Variable* iterator = scope_->DeclarationScope()->NewTemporary(
2804  heap_factory->dot_iterator_string());
2805  Variable* result = scope_->DeclarationScope()->NewTemporary(
2806  heap_factory->dot_result_string());
2807 
2808  Expression* assign_iterator;
2809  Expression* next_result;
2810  Expression* result_done;
2811  Expression* assign_each;
2812 
2813  // var iterator = iterable;
2814  {
2815  Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
2816  assign_iterator = factory()->NewAssignment(
2817  Token::ASSIGN, iterator_proxy, subject, RelocInfo::kNoPosition);
2818  }
2819 
2820  // var result = iterator.next();
2821  {
2822  Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
2823  Expression* next_literal = factory()->NewLiteral(
2824  heap_factory->next_string(), RelocInfo::kNoPosition);
2825  Expression* next_property = factory()->NewProperty(
2826  iterator_proxy, next_literal, RelocInfo::kNoPosition);
2827  ZoneList<Expression*>* next_arguments =
2828  new(zone()) ZoneList<Expression*>(0, zone());
2829  Expression* next_call = factory()->NewCall(
2830  next_property, next_arguments, RelocInfo::kNoPosition);
2831  Expression* result_proxy = factory()->NewVariableProxy(result);
2832  next_result = factory()->NewAssignment(
2833  Token::ASSIGN, result_proxy, next_call, RelocInfo::kNoPosition);
2834  }
2835 
2836  // result.done
2837  {
2838  Expression* done_literal = factory()->NewLiteral(
2839  heap_factory->done_string(), RelocInfo::kNoPosition);
2840  Expression* result_proxy = factory()->NewVariableProxy(result);
2841  result_done = factory()->NewProperty(
2842  result_proxy, done_literal, RelocInfo::kNoPosition);
2843  }
2844 
2845  // each = result.value
2846  {
2847  Expression* value_literal = factory()->NewLiteral(
2848  heap_factory->value_string(), RelocInfo::kNoPosition);
2849  Expression* result_proxy = factory()->NewVariableProxy(result);
2850  Expression* result_value = factory()->NewProperty(
2851  result_proxy, value_literal, RelocInfo::kNoPosition);
2852  assign_each = factory()->NewAssignment(
2853  Token::ASSIGN, each, result_value, RelocInfo::kNoPosition);
2854  }
2855 
2856  for_of->Initialize(each, subject, body,
2857  assign_iterator, next_result, result_done, assign_each);
2858  } else {
2859  stmt->Initialize(each, subject, body);
2860  }
2861 }
2862 
2863 
2864 Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
2865  // ForStatement ::
2866  // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
2867 
2868  int pos = peek_position();
2869  Statement* init = NULL;
2870 
2871  // Create an in-between scope for let-bound iteration variables.
2872  Scope* saved_scope = scope_;
2873  Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
2874  scope_ = for_scope;
2875 
2876  Expect(Token::FOR, CHECK_OK);
2877  Expect(Token::LPAREN, CHECK_OK);
2878  for_scope->set_start_position(scanner()->location().beg_pos);
2879  if (peek() != Token::SEMICOLON) {
2880  if (peek() == Token::VAR || peek() == Token::CONST) {
2881  bool is_const = peek() == Token::CONST;
2882  Handle<String> name;
2883  VariableDeclarationProperties decl_props = kHasNoInitializers;
2884  Block* variable_statement =
2885  ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
2886  CHECK_OK);
2887  bool accept_OF = decl_props == kHasNoInitializers;
2889 
2890  if (!name.is_null() && CheckInOrOf(accept_OF, &mode)) {
2891  Interface* interface =
2892  is_const ? Interface::NewConst() : Interface::NewValue();
2893  ForEachStatement* loop =
2894  factory()->NewForEachStatement(mode, labels, pos);
2895  Target target(&this->target_stack_, loop);
2896 
2897  Expression* enumerable = ParseExpression(true, CHECK_OK);
2898  Expect(Token::RPAREN, CHECK_OK);
2899 
2900  VariableProxy* each =
2901  scope_->NewUnresolved(factory(), name, interface);
2902  Statement* body = ParseStatement(NULL, CHECK_OK);
2903  InitializeForEachStatement(loop, each, enumerable, body);
2904  Block* result =
2905  factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
2906  result->AddStatement(variable_statement, zone());
2907  result->AddStatement(loop, zone());
2908  scope_ = saved_scope;
2909  for_scope->set_end_position(scanner()->location().end_pos);
2910  for_scope = for_scope->FinalizeBlockScope();
2911  ASSERT(for_scope == NULL);
2912  // Parsed for-in loop w/ variable/const declaration.
2913  return result;
2914  } else {
2915  init = variable_statement;
2916  }
2917  } else if (peek() == Token::LET) {
2918  Handle<String> name;
2919  VariableDeclarationProperties decl_props = kHasNoInitializers;
2920  Block* variable_statement =
2921  ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
2922  CHECK_OK);
2923  bool accept_IN = !name.is_null() && decl_props != kHasInitializers;
2924  bool accept_OF = decl_props == kHasNoInitializers;
2926 
2927  if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
2928  // Rewrite a for-in statement of the form
2929  //
2930  // for (let x in e) b
2931  //
2932  // into
2933  //
2934  // <let x' be a temporary variable>
2935  // for (x' in e) {
2936  // let x;
2937  // x = x';
2938  // b;
2939  // }
2940 
2941  // TODO(keuchel): Move the temporary variable to the block scope, after
2942  // implementing stack allocated block scoped variables.
2943  Factory* heap_factory = isolate()->factory();
2944  Handle<String> tempstr =
2945  heap_factory->NewConsString(heap_factory->dot_for_string(), name);
2946  RETURN_IF_EMPTY_HANDLE_VALUE(isolate(), tempstr, 0);
2947  Handle<String> tempname = heap_factory->InternalizeString(tempstr);
2948  Variable* temp = scope_->DeclarationScope()->NewTemporary(tempname);
2949  VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
2950  ForEachStatement* loop =
2951  factory()->NewForEachStatement(mode, labels, pos);
2952  Target target(&this->target_stack_, loop);
2953 
2954  // The expression does not see the loop variable.
2955  scope_ = saved_scope;
2956  Expression* enumerable = ParseExpression(true, CHECK_OK);
2957  scope_ = for_scope;
2958  Expect(Token::RPAREN, CHECK_OK);
2959 
2960  VariableProxy* each =
2961  scope_->NewUnresolved(factory(), name, Interface::NewValue());
2962  Statement* body = ParseStatement(NULL, CHECK_OK);
2963  Block* body_block =
2964  factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
2965  Assignment* assignment = factory()->NewAssignment(
2966  Token::ASSIGN, each, temp_proxy, RelocInfo::kNoPosition);
2967  Statement* assignment_statement = factory()->NewExpressionStatement(
2968  assignment, RelocInfo::kNoPosition);
2969  body_block->AddStatement(variable_statement, zone());
2970  body_block->AddStatement(assignment_statement, zone());
2971  body_block->AddStatement(body, zone());
2972  InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
2973  scope_ = saved_scope;
2974  for_scope->set_end_position(scanner()->location().end_pos);
2975  for_scope = for_scope->FinalizeBlockScope();
2976  body_block->set_scope(for_scope);
2977  // Parsed for-in loop w/ let declaration.
2978  return loop;
2979 
2980  } else {
2981  init = variable_statement;
2982  }
2983  } else {
2984  Scanner::Location lhs_location = scanner()->peek_location();
2985  Expression* expression = ParseExpression(false, CHECK_OK);
2987  bool accept_OF = expression->AsVariableProxy();
2988 
2989  if (CheckInOrOf(accept_OF, &mode)) {
2990  if (expression == NULL || !expression->IsValidLeftHandSide()) {
2991  ReportMessageAt(lhs_location, "invalid_lhs_in_for", true);
2992  *ok = false;
2993  return NULL;
2994  }
2995  ForEachStatement* loop =
2996  factory()->NewForEachStatement(mode, labels, pos);
2997  Target target(&this->target_stack_, loop);
2998 
2999  Expression* enumerable = ParseExpression(true, CHECK_OK);
3000  Expect(Token::RPAREN, CHECK_OK);
3001 
3002  Statement* body = ParseStatement(NULL, CHECK_OK);
3003  InitializeForEachStatement(loop, expression, enumerable, body);
3004  scope_ = saved_scope;
3005  for_scope->set_end_position(scanner()->location().end_pos);
3006  for_scope = for_scope->FinalizeBlockScope();
3007  ASSERT(for_scope == NULL);
3008  // Parsed for-in loop.
3009  return loop;
3010 
3011  } else {
3012  init = factory()->NewExpressionStatement(
3013  expression, RelocInfo::kNoPosition);
3014  }
3015  }
3016  }
3017 
3018  // Standard 'for' loop
3019  ForStatement* loop = factory()->NewForStatement(labels, pos);
3020  Target target(&this->target_stack_, loop);
3021 
3022  // Parsed initializer at this point.
3023  Expect(Token::SEMICOLON, CHECK_OK);
3024 
3025  Expression* cond = NULL;
3026  if (peek() != Token::SEMICOLON) {
3027  cond = ParseExpression(true, CHECK_OK);
3028  }
3029  Expect(Token::SEMICOLON, CHECK_OK);
3030 
3031  Statement* next = NULL;
3032  if (peek() != Token::RPAREN) {
3033  Expression* exp = ParseExpression(true, CHECK_OK);
3034  next = factory()->NewExpressionStatement(exp, RelocInfo::kNoPosition);
3035  }
3036  Expect(Token::RPAREN, CHECK_OK);
3037 
3038  Statement* body = ParseStatement(NULL, CHECK_OK);
3039  scope_ = saved_scope;
3040  for_scope->set_end_position(scanner()->location().end_pos);
3041  for_scope = for_scope->FinalizeBlockScope();
3042  if (for_scope != NULL) {
3043  // Rewrite a for statement of the form
3044  //
3045  // for (let x = i; c; n) b
3046  //
3047  // into
3048  //
3049  // {
3050  // let x = i;
3051  // for (; c; n) b
3052  // }
3053  ASSERT(init != NULL);
3054  Block* result = factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3055  result->AddStatement(init, zone());
3056  result->AddStatement(loop, zone());
3057  result->set_scope(for_scope);
3058  loop->Initialize(NULL, cond, next, body);
3059  return result;
3060  } else {
3061  loop->Initialize(init, cond, next, body);
3062  return loop;
3063  }
3064 }
3065 
3066 
3067 DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
3068  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
3069  // contexts this is used as a statement which invokes the debugger as i a
3070  // break point is present.
3071  // DebuggerStatement ::
3072  // 'debugger' ';'
3073 
3074  int pos = peek_position();
3075  Expect(Token::DEBUGGER, CHECK_OK);
3077  return factory()->NewDebuggerStatement(pos);
3078 }
3079 
3080 
3081 void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
3082  SmartArrayPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
3083  const char* element[1] = { name_string.get() };
3084  ReportMessage("invalid_preparser_data",
3085  Vector<const char*>(element, 1));
3086  *ok = false;
3087 }
3088 
3089 
3091  if (expression->AsLiteral() != NULL) return true;
3092  MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3093  return lit != NULL && lit->is_simple();
3094 }
3095 
3096 
3098  Expression* expression) {
3099  Factory* factory = isolate->factory();
3100  ASSERT(IsCompileTimeValue(expression));
3101  Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
3102  ObjectLiteral* object_literal = expression->AsObjectLiteral();
3103  if (object_literal != NULL) {
3104  ASSERT(object_literal->is_simple());
3105  if (object_literal->fast_elements()) {
3106  result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3107  } else {
3108  result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3109  }
3110  result->set(kElementsSlot, *object_literal->constant_properties());
3111  } else {
3112  ArrayLiteral* array_literal = expression->AsArrayLiteral();
3113  ASSERT(array_literal != NULL && array_literal->is_simple());
3114  result->set(kLiteralTypeSlot, Smi::FromInt(ARRAY_LITERAL));
3115  result->set(kElementsSlot, *array_literal->constant_elements());
3116  }
3117  return result;
3118 }
3119 
3120 
3122  Handle<FixedArray> value) {
3123  Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
3124  return static_cast<LiteralType>(literal_type->value());
3125 }
3126 
3127 
3129  return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3130 }
3131 
3132 
3133 FunctionLiteral* Parser::ParseFunctionLiteral(
3134  Handle<String> function_name,
3135  Scanner::Location function_name_location,
3136  bool name_is_strict_reserved,
3137  bool is_generator,
3138  int function_token_pos,
3139  FunctionLiteral::FunctionType function_type,
3140  bool* ok) {
3141  // Function ::
3142  // '(' FormalParameterList? ')' '{' FunctionBody '}'
3143 
3144  int pos = function_token_pos == RelocInfo::kNoPosition
3145  ? peek_position() : function_token_pos;
3146 
3147  // Anonymous functions were passed either the empty symbol or a null
3148  // handle as the function name. Remember if we were passed a non-empty
3149  // handle to decide whether to invoke function name inference.
3150  bool should_infer_name = function_name.is_null();
3151 
3152  // We want a non-null handle as the function name.
3153  if (should_infer_name) {
3154  function_name = isolate()->factory()->empty_string();
3155  }
3156 
3157  int num_parameters = 0;
3158  // Function declarations are function scoped in normal mode, so they are
3159  // hoisted. In harmony block scoping mode they are block scoped, so they
3160  // are not hoisted.
3161  //
3162  // One tricky case are function declarations in a local sloppy-mode eval:
3163  // their declaration is hoisted, but they still see the local scope. E.g.,
3164  //
3165  // function() {
3166  // var x = 0
3167  // try { throw 1 } catch (x) { eval("function g() { return x }") }
3168  // return g()
3169  // }
3170  //
3171  // needs to return 1. To distinguish such cases, we need to detect
3172  // (1) whether a function stems from a sloppy eval, and
3173  // (2) whether it actually hoists across the eval.
3174  // Unfortunately, we do not represent sloppy eval scopes, so we do not have
3175  // either information available directly, especially not when lazily compiling
3176  // a function like 'g'. We hence rely on the following invariants:
3177  // - (1) is the case iff the innermost scope of the deserialized scope chain
3178  // under which we compile is _not_ a declaration scope. This holds because
3179  // in all normal cases, function declarations are fully hoisted to a
3180  // declaration scope and compiled relative to that.
3181  // - (2) is the case iff the current declaration scope is still the original
3182  // one relative to the deserialized scope chain. Otherwise we must be
3183  // compiling a function in an inner declaration scope in the eval, e.g. a
3184  // nested function, and hoisting works normally relative to that.
3185  Scope* declaration_scope = scope_->DeclarationScope();
3186  Scope* original_declaration_scope = original_scope_->DeclarationScope();
3187  Scope* scope =
3188  function_type == FunctionLiteral::DECLARATION &&
3189  (!allow_harmony_scoping() || strict_mode() == SLOPPY) &&
3190  (original_scope_ == original_declaration_scope ||
3191  declaration_scope != original_declaration_scope)
3192  ? NewScope(declaration_scope, FUNCTION_SCOPE)
3193  : NewScope(scope_, FUNCTION_SCOPE);
3194  ZoneList<Statement*>* body = NULL;
3195  int materialized_literal_count = -1;
3196  int expected_property_count = -1;
3197  int handler_count = 0;
3198  FunctionLiteral::ParameterFlag duplicate_parameters =
3199  FunctionLiteral::kNoDuplicateParameters;
3200  FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_
3201  ? FunctionLiteral::kIsParenthesized
3202  : FunctionLiteral::kNotParenthesized;
3203  FunctionLiteral::IsGeneratorFlag generator = is_generator
3204  ? FunctionLiteral::kIsGenerator
3205  : FunctionLiteral::kNotGenerator;
3206  DeferredFeedbackSlotProcessor* slot_processor;
3207  AstProperties ast_properties;
3208  BailoutReason dont_optimize_reason = kNoReason;
3209  // Parse function body.
3210  { FunctionState function_state(&function_state_, &scope_, scope, zone());
3211  scope_->SetScopeName(function_name);
3212 
3213  if (is_generator) {
3214  // For generators, allocating variables in contexts is currently a win
3215  // because it minimizes the work needed to suspend and resume an
3216  // activation.
3217  scope_->ForceContextAllocation();
3218 
3219  // Calling a generator returns a generator object. That object is stored
3220  // in a temporary variable, a definition that is used by "yield"
3221  // expressions. This also marks the FunctionState as a generator.
3222  Variable* temp = scope_->DeclarationScope()->NewTemporary(
3223  isolate()->factory()->dot_generator_object_string());
3224  function_state.set_generator_object_variable(temp);
3225  }
3226 
3227  // FormalParameterList ::
3228  // '(' (Identifier)*[','] ')'
3229  Expect(Token::LPAREN, CHECK_OK);
3230  scope->set_start_position(scanner()->location().beg_pos);
3231 
3232  // We don't yet know if the function will be strict, so we cannot yet
3233  // produce errors for parameter names or duplicates. However, we remember
3234  // the locations of these errors if they occur and produce the errors later.
3235  Scanner::Location eval_args_error_log = Scanner::Location::invalid();
3236  Scanner::Location dupe_error_loc = Scanner::Location::invalid();
3237  Scanner::Location reserved_loc = Scanner::Location::invalid();
3238 
3239  bool done = (peek() == Token::RPAREN);
3240  while (!done) {
3241  bool is_strict_reserved = false;
3242  Handle<String> param_name =
3243  ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
3244 
3245  // Store locations for possible future error reports.
3246  if (!eval_args_error_log.IsValid() && IsEvalOrArguments(param_name)) {
3247  eval_args_error_log = scanner()->location();
3248  }
3249  if (!reserved_loc.IsValid() && is_strict_reserved) {
3250  reserved_loc = scanner()->location();
3251  }
3252  if (!dupe_error_loc.IsValid() && scope_->IsDeclared(param_name)) {
3253  duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
3254  dupe_error_loc = scanner()->location();
3255  }
3256 
3257  scope_->DeclareParameter(param_name, VAR);
3258  num_parameters++;
3259  if (num_parameters > Code::kMaxArguments) {
3260  ReportMessageAt(scanner()->location(), "too_many_parameters");
3261  *ok = false;
3262  return NULL;
3263  }
3264  done = (peek() == Token::RPAREN);
3265  if (!done) Expect(Token::COMMA, CHECK_OK);
3266  }
3267  Expect(Token::RPAREN, CHECK_OK);
3268 
3269  Expect(Token::LBRACE, CHECK_OK);
3270 
3271  // If we have a named function expression, we add a local variable
3272  // declaration to the body of the function with the name of the
3273  // function and let it refer to the function itself (closure).
3274  // NOTE: We create a proxy and resolve it here so that in the
3275  // future we can change the AST to only refer to VariableProxies
3276  // instead of Variables and Proxis as is the case now.
3277  Variable* fvar = NULL;
3278  Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
3279  if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
3280  if (allow_harmony_scoping() && strict_mode() == STRICT) {
3281  fvar_init_op = Token::INIT_CONST;
3282  }
3283  VariableMode fvar_mode =
3285  : CONST_LEGACY;
3286  fvar = new(zone()) Variable(scope_,
3287  function_name, fvar_mode, true /* is valid LHS */,
3289  VariableProxy* proxy = factory()->NewVariableProxy(fvar);
3290  VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
3291  proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
3292  scope_->DeclareFunctionVar(fvar_declaration);
3293  }
3294 
3295  // Determine if the function can be parsed lazily. Lazy parsing is different
3296  // from lazy compilation; we need to parse more eagerly than we compile.
3297 
3298  // We can only parse lazily if we also compile lazily. The heuristics for
3299  // lazy compilation are:
3300  // - It must not have been prohibited by the caller to Parse (some callers
3301  // need a full AST).
3302  // - The outer scope must allow lazy compilation of inner functions.
3303  // - The function mustn't be a function expression with an open parenthesis
3304  // before; we consider that a hint that the function will be called
3305  // immediately, and it would be a waste of time to make it lazily
3306  // compiled.
3307  // These are all things we can know at this point, without looking at the
3308  // function itself.
3309 
3310  // In addition, we need to distinguish between these cases:
3311  // (function foo() {
3312  // bar = function() { return 1; }
3313  // })();
3314  // and
3315  // (function foo() {
3316  // var a = 1;
3317  // bar = function() { return a; }
3318  // })();
3319 
3320  // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
3321  // parenthesis before the function means that it will be called
3322  // immediately). The inner function *must* be parsed eagerly to resolve the
3323  // possible reference to the variable in foo's scope. However, it's possible
3324  // that it will be compiled lazily.
3325 
3326  // To make this additional case work, both Parser and PreParser implement a
3327  // logic where only top-level functions will be parsed lazily.
3328  bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
3329  scope_->AllowsLazyCompilation() &&
3331  parenthesized_function_ = false; // The bit was set for this function only.
3332 
3333  if (is_lazily_parsed) {
3334  int function_block_pos = position();
3335  FunctionEntry entry;
3336  if (cached_data_mode_ == CONSUME_CACHED_DATA) {
3337  // If we have cached data, we use it to skip parsing the function body.
3338  // The data contains the information we need to construct the lazy
3339  // function.
3340  entry = (*cached_data())->GetFunctionEntry(function_block_pos);
3341  if (entry.is_valid()) {
3342  if (entry.end_pos() <= function_block_pos) {
3343  // End position greater than end of stream is safe, and hard
3344  // to check.
3345  ReportInvalidPreparseData(function_name, CHECK_OK);
3346  }
3347  scanner()->SeekForward(entry.end_pos() - 1);
3348 
3349  scope->set_end_position(entry.end_pos());
3350  Expect(Token::RBRACE, CHECK_OK);
3351  isolate()->counters()->total_preparse_skipped()->Increment(
3352  scope->end_position() - function_block_pos);
3353  materialized_literal_count = entry.literal_count();
3354  expected_property_count = entry.property_count();
3355  scope_->SetStrictMode(entry.strict_mode());
3356  } else {
3357  // This case happens when we have preparse data but it doesn't contain
3358  // an entry for the function. As a safety net, fall back to eager
3359  // parsing. It is unclear whether PreParser's laziness analysis can
3360  // produce different results than the Parser's laziness analysis (see
3361  // https://codereview.chromium.org/7565003 ). In this case, we must
3362  // discard all the preparse data, since the symbol data will be wrong.
3363  is_lazily_parsed = false;
3364  cached_data_mode_ = NO_CACHED_DATA;
3365  }
3366  } else {
3367  // With no cached data, we partially parse the function, without
3368  // building an AST. This gathers the data needed to build a lazy
3369  // function.
3370  // FIXME(marja): Now the PreParser doesn't need to log functions /
3371  // symbols; only errors -> clean that up.
3372  SingletonLogger logger;
3373  PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger);
3374  if (result == PreParser::kPreParseStackOverflow) {
3375  // Propagate stack overflow.
3377  *ok = false;
3378  return NULL;
3379  }
3380  if (logger.has_error()) {
3381  const char* arg = logger.argument_opt();
3382  Vector<const char*> args;
3383  if (arg != NULL) {
3384  args = Vector<const char*>(&arg, 1);
3385  }
3387  Scanner::Location(logger.start(), logger.end()),
3388  logger.message(),
3389  args);
3390  *ok = false;
3391  return NULL;
3392  }
3393  scope->set_end_position(logger.end());
3394  Expect(Token::RBRACE, CHECK_OK);
3395  isolate()->counters()->total_preparse_skipped()->Increment(
3396  scope->end_position() - function_block_pos);
3397  materialized_literal_count = logger.literals();
3398  expected_property_count = logger.properties();
3399  scope_->SetStrictMode(logger.strict_mode());
3400  if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
3401  ASSERT(log_);
3402  // Position right after terminal '}'.
3403  int body_end = scanner()->location().end_pos;
3404  log_->LogFunction(function_block_pos, body_end,
3405  materialized_literal_count,
3406  expected_property_count,
3407  scope_->strict_mode());
3408  }
3409  }
3410  }
3411 
3412  if (!is_lazily_parsed) {
3413  // Everything inside an eagerly parsed function will be parsed eagerly
3414  // (see comment above).
3415  ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
3416  body = new(zone()) ZoneList<Statement*>(8, zone());
3417  if (fvar != NULL) {
3418  VariableProxy* fproxy = scope_->NewUnresolved(
3419  factory(), function_name, Interface::NewConst());
3420  fproxy->BindTo(fvar);
3421  body->Add(factory()->NewExpressionStatement(
3422  factory()->NewAssignment(fvar_init_op,
3423  fproxy,
3424  factory()->NewThisFunction(pos),
3425  RelocInfo::kNoPosition),
3426  RelocInfo::kNoPosition), zone());
3427  }
3428 
3429  // For generators, allocate and yield an iterator on function entry.
3430  if (is_generator) {
3431  ZoneList<Expression*>* arguments =
3432  new(zone()) ZoneList<Expression*>(0, zone());
3433  CallRuntime* allocation = factory()->NewCallRuntime(
3434  isolate()->factory()->empty_string(),
3435  Runtime::FunctionForId(Runtime::kHiddenCreateJSGeneratorObject),
3436  arguments, pos);
3437  VariableProxy* init_proxy = factory()->NewVariableProxy(
3438  function_state_->generator_object_variable());
3439  Assignment* assignment = factory()->NewAssignment(
3440  Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
3441  VariableProxy* get_proxy = factory()->NewVariableProxy(
3442  function_state_->generator_object_variable());
3443  Yield* yield = factory()->NewYield(
3444  get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition);
3445  body->Add(factory()->NewExpressionStatement(
3446  yield, RelocInfo::kNoPosition), zone());
3447  }
3448 
3449  ParseSourceElements(body, Token::RBRACE, false, false, CHECK_OK);
3450 
3451  if (is_generator) {
3452  VariableProxy* get_proxy = factory()->NewVariableProxy(
3453  function_state_->generator_object_variable());
3454  Expression *undefined = factory()->NewLiteral(
3455  isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
3456  Yield* yield = factory()->NewYield(
3457  get_proxy, undefined, Yield::FINAL, RelocInfo::kNoPosition);
3458  body->Add(factory()->NewExpressionStatement(
3459  yield, RelocInfo::kNoPosition), zone());
3460  }
3461 
3462  materialized_literal_count = function_state.materialized_literal_count();
3463  expected_property_count = function_state.expected_property_count();
3464  handler_count = function_state.handler_count();
3465 
3466  Expect(Token::RBRACE, CHECK_OK);
3467  scope->set_end_position(scanner()->location().end_pos);
3468  }
3469 
3470  // Validate strict mode. We can do this only after parsing the function,
3471  // since the function can declare itself strict.
3472  if (strict_mode() == STRICT) {
3473  if (IsEvalOrArguments(function_name)) {
3474  ReportMessageAt(function_name_location, "strict_eval_arguments");
3475  *ok = false;
3476  return NULL;
3477  }
3478  if (name_is_strict_reserved) {
3479  ReportMessageAt(function_name_location, "unexpected_strict_reserved");
3480  *ok = false;
3481  return NULL;
3482  }
3483  if (eval_args_error_log.IsValid()) {
3484  ReportMessageAt(eval_args_error_log, "strict_eval_arguments");
3485  *ok = false;
3486  return NULL;
3487  }
3488  if (dupe_error_loc.IsValid()) {
3489  ReportMessageAt(dupe_error_loc, "strict_param_dupe");
3490  *ok = false;
3491  return NULL;
3492  }
3493  if (reserved_loc.IsValid()) {
3494  ReportMessageAt(reserved_loc, "unexpected_strict_reserved");
3495  *ok = false;
3496  return NULL;
3497  }
3498  CheckOctalLiteral(scope->start_position(),
3499  scope->end_position(),
3500  CHECK_OK);
3501  }
3502  ast_properties = *factory()->visitor()->ast_properties();
3503  slot_processor = factory()->visitor()->slot_processor();
3504  dont_optimize_reason = factory()->visitor()->dont_optimize_reason();
3505  }
3506 
3507  if (allow_harmony_scoping() && strict_mode() == STRICT) {
3508  CheckConflictingVarDeclarations(scope, CHECK_OK);
3509  }
3510 
3511  FunctionLiteral* function_literal =
3512  factory()->NewFunctionLiteral(function_name,
3513  scope,
3514  body,
3515  materialized_literal_count,
3516  expected_property_count,
3517  handler_count,
3518  num_parameters,
3519  duplicate_parameters,
3520  function_type,
3521  FunctionLiteral::kIsFunction,
3522  parenthesized,
3523  generator,
3524  pos);
3525  function_literal->set_function_token_position(function_token_pos);
3526  function_literal->set_ast_properties(&ast_properties);
3527  function_literal->set_slot_processor(slot_processor);
3528  function_literal->set_dont_optimize_reason(dont_optimize_reason);
3529 
3530  if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
3531  return function_literal;
3532 }
3533 
3534 
3535 PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
3536  SingletonLogger* logger) {
3537  HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse());
3538  ASSERT_EQ(Token::LBRACE, scanner()->current_token());
3539 
3540  if (reusable_preparser_ == NULL) {
3541  intptr_t stack_limit = isolate()->stack_guard()->real_climit();
3542  reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit);
3543  reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
3544  reusable_preparser_->set_allow_modules(allow_modules());
3545  reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax());
3546  reusable_preparser_->set_allow_lazy(true);
3547  reusable_preparser_->set_allow_generators(allow_generators());
3548  reusable_preparser_->set_allow_for_of(allow_for_of());
3549  reusable_preparser_->set_allow_harmony_numeric_literals(
3551  }
3552  PreParser::PreParseResult result =
3553  reusable_preparser_->PreParseLazyFunction(strict_mode(),
3554  is_generator(),
3555  logger);
3556  return result;
3557 }
3558 
3559 
3560 Expression* Parser::ParseV8Intrinsic(bool* ok) {
3561  // CallRuntime ::
3562  // '%' Identifier Arguments
3563 
3564  int pos = peek_position();
3565  Expect(Token::MOD, CHECK_OK);
3566  // Allow "eval" or "arguments" for backward compatibility.
3567  Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
3568  ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
3569 
3570  if (extension_ != NULL) {
3571  // The extension structures are only accessible while parsing the
3572  // very first time not when reparsing because of lazy compilation.
3573  scope_->DeclarationScope()->ForceEagerCompilation();
3574  }
3575 
3576  const Runtime::Function* function = Runtime::FunctionForName(name);
3577 
3578  // Check for built-in IS_VAR macro.
3579  if (function != NULL &&
3580  function->intrinsic_type == Runtime::RUNTIME &&
3581  function->function_id == Runtime::kIS_VAR) {
3582  // %IS_VAR(x) evaluates to x if x is a variable,
3583  // leads to a parse error otherwise. Could be implemented as an
3584  // inline function %_IS_VAR(x) to eliminate this special case.
3585  if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
3586  return args->at(0);
3587  } else {
3588  ReportMessage("not_isvar", Vector<const char*>::empty());
3589  *ok = false;
3590  return NULL;
3591  }
3592  }
3593 
3594  // Check that the expected number of arguments are being passed.
3595  if (function != NULL &&
3596  function->nargs != -1 &&
3597  function->nargs != args->length()) {
3598  ReportMessage("illegal_access", Vector<const char*>::empty());
3599  *ok = false;
3600  return NULL;
3601  }
3602 
3603  // Check that the function is defined if it's an inline runtime call.
3604  if (function == NULL && name->Get(0) == '_') {
3605  ParserTraits::ReportMessage("not_defined",
3606  Vector<Handle<String> >(&name, 1));
3607  *ok = false;
3608  return NULL;
3609  }
3610 
3611  // We have a valid intrinsics call or a call to a builtin.
3612  return factory()->NewCallRuntime(name, function, args, pos);
3613 }
3614 
3615 
3616 Literal* Parser::GetLiteralUndefined(int position) {
3617  return factory()->NewLiteral(
3618  isolate()->factory()->undefined_value(), position);
3619 }
3620 
3621 
3622 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
3623  Declaration* decl = scope->CheckConflictingVarDeclarations();
3624  if (decl != NULL) {
3625  // In harmony mode we treat conflicting variable bindinds as early
3626  // errors. See ES5 16 for a definition of early errors.
3627  Handle<String> name = decl->proxy()->name();
3628  SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
3629  const char* elms[2] = { "Variable", c_string.get() };
3630  Vector<const char*> args(elms, 2);
3631  int position = decl->proxy()->position();
3632  Scanner::Location location = position == RelocInfo::kNoPosition
3634  : Scanner::Location(position, position + 1);
3635  ParserTraits::ReportMessageAt(location, "redeclaration", args);
3636  *ok = false;
3637  }
3638 }
3639 
3640 
3641 // ----------------------------------------------------------------------------
3642 // Parser support
3643 
3644 
3645 bool Parser::TargetStackContainsLabel(Handle<String> label) {
3646  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3647  BreakableStatement* stat = t->node()->AsBreakableStatement();
3648  if (stat != NULL && ContainsLabel(stat->labels(), label))
3649  return true;
3650  }
3651  return false;
3652 }
3653 
3654 
3655 BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
3656  bool anonymous = label.is_null();
3657  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3658  BreakableStatement* stat = t->node()->AsBreakableStatement();
3659  if (stat == NULL) continue;
3660  if ((anonymous && stat->is_target_for_anonymous()) ||
3661  (!anonymous && ContainsLabel(stat->labels(), label))) {
3662  RegisterTargetUse(stat->break_target(), t->previous());
3663  return stat;
3664  }
3665  }
3666  return NULL;
3667 }
3668 
3669 
3670 IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
3671  bool* ok) {
3672  bool anonymous = label.is_null();
3673  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3674  IterationStatement* stat = t->node()->AsIterationStatement();
3675  if (stat == NULL) continue;
3676 
3677  ASSERT(stat->is_target_for_anonymous());
3678  if (anonymous || ContainsLabel(stat->labels(), label)) {
3679  RegisterTargetUse(stat->continue_target(), t->previous());
3680  return stat;
3681  }
3682  }
3683  return NULL;
3684 }
3685 
3686 
3687 void Parser::RegisterTargetUse(Label* target, Target* stop) {
3688  // Register that a break target found at the given stop in the
3689  // target stack has been used from the top of the target stack. Add
3690  // the break target to any TargetCollectors passed on the stack.
3691  for (Target* t = target_stack_; t != stop; t = t->previous()) {
3692  TargetCollector* collector = t->node()->AsTargetCollector();
3693  if (collector != NULL) collector->AddTarget(target, zone());
3694  }
3695 }
3696 
3697 
3698 Expression* Parser::NewThrowReferenceError(Handle<String> message) {
3699  return NewThrowError(isolate()->factory()->MakeReferenceError_string(),
3700  message, HandleVector<Object>(NULL, 0));
3701 }
3702 
3703 
3704 Expression* Parser::NewThrowSyntaxError(Handle<String> message,
3705  Handle<Object> first) {
3706  int argc = first.is_null() ? 0 : 1;
3707  Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
3708  return NewThrowError(
3709  isolate()->factory()->MakeSyntaxError_string(), message, arguments);
3710 }
3711 
3712 
3713 Expression* Parser::NewThrowTypeError(Handle<String> message,
3714  Handle<Object> first,
3715  Handle<Object> second) {
3716  ASSERT(!first.is_null() && !second.is_null());
3717  Handle<Object> elements[] = { first, second };
3718  Vector< Handle<Object> > arguments =
3719  HandleVector<Object>(elements, ARRAY_SIZE(elements));
3720  return NewThrowError(
3721  isolate()->factory()->MakeTypeError_string(), message, arguments);
3722 }
3723 
3724 
3725 Expression* Parser::NewThrowError(Handle<String> constructor,
3726  Handle<String> message,
3727  Vector< Handle<Object> > arguments) {
3728  int argc = arguments.length();
3729  Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc,
3730  TENURED);
3731  for (int i = 0; i < argc; i++) {
3732  Handle<Object> element = arguments[i];
3733  if (!element.is_null()) {
3734  elements->set(i, *element);
3735  }
3736  }
3737  Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(
3738  elements, FAST_ELEMENTS, TENURED);
3739 
3740  int pos = position();
3741  ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2, zone());
3742  args->Add(factory()->NewLiteral(message, pos), zone());
3743  args->Add(factory()->NewLiteral(array, pos), zone());
3744  CallRuntime* call_constructor =
3745  factory()->NewCallRuntime(constructor, NULL, args, pos);
3746  return factory()->NewThrow(call_constructor, pos);
3747 }
3748 
3749 
3750 // ----------------------------------------------------------------------------
3751 // Regular expressions
3752 
3753 
3754 RegExpParser::RegExpParser(FlatStringReader* in,
3755  Handle<String>* error,
3756  bool multiline,
3757  Zone* zone)
3758  : isolate_(zone->isolate()),
3759  zone_(zone),
3760  error_(error),
3761  captures_(NULL),
3762  in_(in),
3763  current_(kEndMarker),
3764  next_pos_(0),
3765  capture_count_(0),
3766  has_more_(true),
3767  multiline_(multiline),
3768  simple_(false),
3769  contains_anchor_(false),
3770  is_scanned_for_captures_(false),
3771  failed_(false) {
3772  Advance();
3773 }
3774 
3775 
3776 uc32 RegExpParser::Next() {
3777  if (has_next()) {
3778  return in()->Get(next_pos_);
3779  } else {
3780  return kEndMarker;
3781  }
3782 }
3783 
3784 
3785 void RegExpParser::Advance() {
3786  if (next_pos_ < in()->length()) {
3787  StackLimitCheck check(isolate());
3788  if (check.HasOverflowed()) {
3790  } else if (zone()->excess_allocation()) {
3791  ReportError(CStrVector("Regular expression too large"));
3792  } else {
3793  current_ = in()->Get(next_pos_);
3794  next_pos_++;
3795  }
3796  } else {
3797  current_ = kEndMarker;
3798  has_more_ = false;
3799  }
3800 }
3801 
3802 
3803 void RegExpParser::Reset(int pos) {
3804  next_pos_ = pos;
3805  has_more_ = (pos < in()->length());
3806  Advance();
3807 }
3808 
3809 
3810 void RegExpParser::Advance(int dist) {
3811  next_pos_ += dist - 1;
3812  Advance();
3813 }
3814 
3815 
3816 bool RegExpParser::simple() {
3817  return simple_;
3818 }
3819 
3820 
3821 RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
3822  failed_ = true;
3823  *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
3824  ASSERT(!error_->is_null());
3825  // Zip to the end to make sure the no more input is read.
3826  current_ = kEndMarker;
3827  next_pos_ = in()->length();
3828  return NULL;
3829 }
3830 
3831 
3832 // Pattern ::
3833 // Disjunction
3834 RegExpTree* RegExpParser::ParsePattern() {
3835  RegExpTree* result = ParseDisjunction(CHECK_FAILED);
3836  ASSERT(!has_more());
3837  // If the result of parsing is a literal string atom, and it has the
3838  // same length as the input, then the atom is identical to the input.
3839  if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
3840  simple_ = true;
3841  }
3842  return result;
3843 }
3844 
3845 
3846 // Disjunction ::
3847 // Alternative
3848 // Alternative | Disjunction
3849 // Alternative ::
3850 // [empty]
3851 // Term Alternative
3852 // Term ::
3853 // Assertion
3854 // Atom
3855 // Atom Quantifier
3856 RegExpTree* RegExpParser::ParseDisjunction() {
3857  // Used to store current state while parsing subexpressions.
3858  RegExpParserState initial_state(NULL, INITIAL, 0, zone());
3859  RegExpParserState* stored_state = &initial_state;
3860  // Cache the builder in a local variable for quick access.
3861  RegExpBuilder* builder = initial_state.builder();
3862  while (true) {
3863  switch (current()) {
3864  case kEndMarker:
3865  if (stored_state->IsSubexpression()) {
3866  // Inside a parenthesized group when hitting end of input.
3867  ReportError(CStrVector("Unterminated group") CHECK_FAILED);
3868  }
3869  ASSERT_EQ(INITIAL, stored_state->group_type());
3870  // Parsing completed successfully.
3871  return builder->ToRegExp();
3872  case ')': {
3873  if (!stored_state->IsSubexpression()) {
3874  ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
3875  }
3876  ASSERT_NE(INITIAL, stored_state->group_type());
3877 
3878  Advance();
3879  // End disjunction parsing and convert builder content to new single
3880  // regexp atom.
3881  RegExpTree* body = builder->ToRegExp();
3882 
3883  int end_capture_index = captures_started();
3884 
3885  int capture_index = stored_state->capture_index();
3886  SubexpressionType group_type = stored_state->group_type();
3887 
3888  // Restore previous state.
3889  stored_state = stored_state->previous_state();
3890  builder = stored_state->builder();
3891 
3892  // Build result of subexpression.
3893  if (group_type == CAPTURE) {
3894  RegExpCapture* capture = new(zone()) RegExpCapture(body, capture_index);
3895  captures_->at(capture_index - 1) = capture;
3896  body = capture;
3897  } else if (group_type != GROUPING) {
3898  ASSERT(group_type == POSITIVE_LOOKAHEAD ||
3899  group_type == NEGATIVE_LOOKAHEAD);
3900  bool is_positive = (group_type == POSITIVE_LOOKAHEAD);
3901  body = new(zone()) RegExpLookahead(body,
3902  is_positive,
3903  end_capture_index - capture_index,
3904  capture_index);
3905  }
3906  builder->AddAtom(body);
3907  // For compatability with JSC and ES3, we allow quantifiers after
3908  // lookaheads, and break in all cases.
3909  break;
3910  }
3911  case '|': {
3912  Advance();
3913  builder->NewAlternative();
3914  continue;
3915  }
3916  case '*':
3917  case '+':
3918  case '?':
3919  return ReportError(CStrVector("Nothing to repeat"));
3920  case '^': {
3921  Advance();
3922  if (multiline_) {
3923  builder->AddAssertion(
3924  new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE));
3925  } else {
3926  builder->AddAssertion(
3927  new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT));
3928  set_contains_anchor();
3929  }
3930  continue;
3931  }
3932  case '$': {
3933  Advance();
3934  RegExpAssertion::AssertionType assertion_type =
3935  multiline_ ? RegExpAssertion::END_OF_LINE :
3936  RegExpAssertion::END_OF_INPUT;
3937  builder->AddAssertion(new(zone()) RegExpAssertion(assertion_type));
3938  continue;
3939  }
3940  case '.': {
3941  Advance();
3942  // everything except \x0a, \x0d, \u2028 and \u2029
3943  ZoneList<CharacterRange>* ranges =
3944  new(zone()) ZoneList<CharacterRange>(2, zone());
3945  CharacterRange::AddClassEscape('.', ranges, zone());
3946  RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
3947  builder->AddAtom(atom);
3948  break;
3949  }
3950  case '(': {
3951  SubexpressionType subexpr_type = CAPTURE;
3952  Advance();
3953  if (current() == '?') {
3954  switch (Next()) {
3955  case ':':
3956  subexpr_type = GROUPING;
3957  break;
3958  case '=':
3959  subexpr_type = POSITIVE_LOOKAHEAD;
3960  break;
3961  case '!':
3962  subexpr_type = NEGATIVE_LOOKAHEAD;
3963  break;
3964  default:
3965  ReportError(CStrVector("Invalid group") CHECK_FAILED);
3966  break;
3967  }
3968  Advance(2);
3969  } else {
3970  if (captures_ == NULL) {
3971  captures_ = new(zone()) ZoneList<RegExpCapture*>(2, zone());
3972  }
3973  if (captures_started() >= kMaxCaptures) {
3974  ReportError(CStrVector("Too many captures") CHECK_FAILED);
3975  }
3976  captures_->Add(NULL, zone());
3977  }
3978  // Store current state and begin new disjunction parsing.
3979  stored_state = new(zone()) RegExpParserState(stored_state, subexpr_type,
3980  captures_started(), zone());
3981  builder = stored_state->builder();
3982  continue;
3983  }
3984  case '[': {
3985  RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
3986  builder->AddAtom(atom);
3987  break;
3988  }
3989  // Atom ::
3990  // \ AtomEscape
3991  case '\\':
3992  switch (Next()) {
3993  case kEndMarker:
3994  return ReportError(CStrVector("\\ at end of pattern"));
3995  case 'b':
3996  Advance(2);
3997  builder->AddAssertion(
3998  new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY));
3999  continue;
4000  case 'B':
4001  Advance(2);
4002  builder->AddAssertion(
4003  new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
4004  continue;
4005  // AtomEscape ::
4006  // CharacterClassEscape
4007  //
4008  // CharacterClassEscape :: one of
4009  // d D s S w W
4010  case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
4011  uc32 c = Next();
4012  Advance(2);
4013  ZoneList<CharacterRange>* ranges =
4014  new(zone()) ZoneList<CharacterRange>(2, zone());
4015  CharacterRange::AddClassEscape(c, ranges, zone());
4016  RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
4017  builder->AddAtom(atom);
4018  break;
4019  }
4020  case '1': case '2': case '3': case '4': case '5': case '6':
4021  case '7': case '8': case '9': {
4022  int index = 0;
4023  if (ParseBackReferenceIndex(&index)) {
4024  RegExpCapture* capture = NULL;
4025  if (captures_ != NULL && index <= captures_->length()) {
4026  capture = captures_->at(index - 1);
4027  }
4028  if (capture == NULL) {
4029  builder->AddEmpty();
4030  break;
4031  }
4032  RegExpTree* atom = new(zone()) RegExpBackReference(capture);
4033  builder->AddAtom(atom);
4034  break;
4035  }
4036  uc32 first_digit = Next();
4037  if (first_digit == '8' || first_digit == '9') {
4038  // Treat as identity escape
4039  builder->AddCharacter(first_digit);
4040  Advance(2);
4041  break;
4042  }
4043  }
4044  // FALLTHROUGH
4045  case '0': {
4046  Advance();
4047  uc32 octal = ParseOctalLiteral();
4048  builder->AddCharacter(octal);
4049  break;
4050  }
4051  // ControlEscape :: one of
4052  // f n r t v
4053  case 'f':
4054  Advance(2);
4055  builder->AddCharacter('\f');
4056  break;
4057  case 'n':
4058  Advance(2);
4059  builder->AddCharacter('\n');
4060  break;
4061  case 'r':
4062  Advance(2);
4063  builder->AddCharacter('\r');
4064  break;
4065  case 't':
4066  Advance(2);
4067  builder->AddCharacter('\t');
4068  break;
4069  case 'v':
4070  Advance(2);
4071  builder->AddCharacter('\v');
4072  break;
4073  case 'c': {
4074  Advance();
4075  uc32 controlLetter = Next();
4076  // Special case if it is an ASCII letter.
4077  // Convert lower case letters to uppercase.
4078  uc32 letter = controlLetter & ~('a' ^ 'A');
4079  if (letter < 'A' || 'Z' < letter) {
4080  // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
4081  // This is outside the specification. We match JSC in
4082  // reading the backslash as a literal character instead
4083  // of as starting an escape.
4084  builder->AddCharacter('\\');
4085  } else {
4086  Advance(2);
4087  builder->AddCharacter(controlLetter & 0x1f);
4088  }
4089  break;
4090  }
4091  case 'x': {
4092  Advance(2);
4093  uc32 value;
4094  if (ParseHexEscape(2, &value)) {
4095  builder->AddCharacter(value);
4096  } else {
4097  builder->AddCharacter('x');
4098  }
4099  break;
4100  }
4101  case 'u': {
4102  Advance(2);
4103  uc32 value;
4104  if (ParseHexEscape(4, &value)) {
4105  builder->AddCharacter(value);
4106  } else {
4107  builder->AddCharacter('u');
4108  }
4109  break;
4110  }
4111  default:
4112  // Identity escape.
4113  builder->AddCharacter(Next());
4114  Advance(2);
4115  break;
4116  }
4117  break;
4118  case '{': {
4119  int dummy;
4120  if (ParseIntervalQuantifier(&dummy, &dummy)) {
4121  ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
4122  }
4123  // fallthrough
4124  }
4125  default:
4126  builder->AddCharacter(current());
4127  Advance();
4128  break;
4129  } // end switch(current())
4130 
4131  int min;
4132  int max;
4133  switch (current()) {
4134  // QuantifierPrefix ::
4135  // *
4136  // +
4137  // ?
4138  // {
4139  case '*':
4140  min = 0;
4141  max = RegExpTree::kInfinity;
4142  Advance();
4143  break;
4144  case '+':
4145  min = 1;
4146  max = RegExpTree::kInfinity;
4147  Advance();
4148  break;
4149  case '?':
4150  min = 0;
4151  max = 1;
4152  Advance();
4153  break;
4154  case '{':
4155  if (ParseIntervalQuantifier(&min, &max)) {
4156  if (max < min) {
4157  ReportError(CStrVector("numbers out of order in {} quantifier.")
4158  CHECK_FAILED);
4159  }
4160  break;
4161  } else {
4162  continue;
4163  }
4164  default:
4165  continue;
4166  }
4167  RegExpQuantifier::QuantifierType quantifier_type = RegExpQuantifier::GREEDY;
4168  if (current() == '?') {
4169  quantifier_type = RegExpQuantifier::NON_GREEDY;
4170  Advance();
4171  } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
4172  // FLAG_regexp_possessive_quantifier is a debug-only flag.
4173  quantifier_type = RegExpQuantifier::POSSESSIVE;
4174  Advance();
4175  }
4176  builder->AddQuantifierToAtom(min, max, quantifier_type);
4177  }
4178 }
4179 
4180 
4181 #ifdef DEBUG
4182 // Currently only used in an ASSERT.
4183 static bool IsSpecialClassEscape(uc32 c) {
4184  switch (c) {
4185  case 'd': case 'D':
4186  case 's': case 'S':
4187  case 'w': case 'W':
4188  return true;
4189  default:
4190  return false;
4191  }
4192 }
4193 #endif
4194 
4195 
4196 // In order to know whether an escape is a backreference or not we have to scan
4197 // the entire regexp and find the number of capturing parentheses. However we
4198 // don't want to scan the regexp twice unless it is necessary. This mini-parser
4199 // is called when needed. It can see the difference between capturing and
4200 // noncapturing parentheses and can skip character classes and backslash-escaped
4201 // characters.
4202 void RegExpParser::ScanForCaptures() {
4203  // Start with captures started previous to current position
4204  int capture_count = captures_started();
4205  // Add count of captures after this position.
4206  int n;
4207  while ((n = current()) != kEndMarker) {
4208  Advance();
4209  switch (n) {
4210  case '\\':
4211  Advance();
4212  break;
4213  case '[': {
4214  int c;
4215  while ((c = current()) != kEndMarker) {
4216  Advance();
4217  if (c == '\\') {
4218  Advance();
4219  } else {
4220  if (c == ']') break;
4221  }
4222  }
4223  break;
4224  }
4225  case '(':
4226  if (current() != '?') capture_count++;
4227  break;
4228  }
4229  }
4230  capture_count_ = capture_count;
4231  is_scanned_for_captures_ = true;
4232 }
4233 
4234 
4235 bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
4236  ASSERT_EQ('\\', current());
4237  ASSERT('1' <= Next() && Next() <= '9');
4238  // Try to parse a decimal literal that is no greater than the total number
4239  // of left capturing parentheses in the input.
4240  int start = position();
4241  int value = Next() - '0';
4242  Advance(2);
4243  while (true) {
4244  uc32 c = current();
4245  if (IsDecimalDigit(c)) {
4246  value = 10 * value + (c - '0');
4247  if (value > kMaxCaptures) {
4248  Reset(start);
4249  return false;
4250  }
4251  Advance();
4252  } else {
4253  break;
4254  }
4255  }
4256  if (value > captures_started()) {
4257  if (!is_scanned_for_captures_) {
4258  int saved_position = position();
4259  ScanForCaptures();
4260  Reset(saved_position);
4261  }
4262  if (value > capture_count_) {
4263  Reset(start);
4264  return false;
4265  }
4266  }
4267  *index_out = value;
4268  return true;
4269 }
4270 
4271 
4272 // QuantifierPrefix ::
4273 // { DecimalDigits }
4274 // { DecimalDigits , }
4275 // { DecimalDigits , DecimalDigits }
4276 //
4277 // Returns true if parsing succeeds, and set the min_out and max_out
4278 // values. Values are truncated to RegExpTree::kInfinity if they overflow.
4279 bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
4280  ASSERT_EQ(current(), '{');
4281  int start = position();
4282  Advance();
4283  int min = 0;
4284  if (!IsDecimalDigit(current())) {
4285  Reset(start);
4286  return false;
4287  }
4288  while (IsDecimalDigit(current())) {
4289  int next = current() - '0';
4290  if (min > (RegExpTree::kInfinity - next) / 10) {
4291  // Overflow. Skip past remaining decimal digits and return -1.
4292  do {
4293  Advance();
4294  } while (IsDecimalDigit(current()));
4295  min = RegExpTree::kInfinity;
4296  break;
4297  }
4298  min = 10 * min + next;
4299  Advance();
4300  }
4301  int max = 0;
4302  if (current() == '}') {
4303  max = min;
4304  Advance();
4305  } else if (current() == ',') {
4306  Advance();
4307  if (current() == '}') {
4308  max = RegExpTree::kInfinity;
4309  Advance();
4310  } else {
4311  while (IsDecimalDigit(current())) {
4312  int next = current() - '0';
4313  if (max > (RegExpTree::kInfinity - next) / 10) {
4314  do {
4315  Advance();
4316  } while (IsDecimalDigit(current()));
4317  max = RegExpTree::kInfinity;
4318  break;
4319  }
4320  max = 10 * max + next;
4321  Advance();
4322  }
4323  if (current() != '}') {
4324  Reset(start);
4325  return false;
4326  }
4327  Advance();
4328  }
4329  } else {
4330  Reset(start);
4331  return false;
4332  }
4333  *min_out = min;
4334  *max_out = max;
4335  return true;
4336 }
4337 
4338 
4339 uc32 RegExpParser::ParseOctalLiteral() {
4340  ASSERT(('0' <= current() && current() <= '7') || current() == kEndMarker);
4341  // For compatibility with some other browsers (not all), we parse
4342  // up to three octal digits with a value below 256.
4343  uc32 value = current() - '0';
4344  Advance();
4345  if ('0' <= current() && current() <= '7') {
4346  value = value * 8 + current() - '0';
4347  Advance();
4348  if (value < 32 && '0' <= current() && current() <= '7') {
4349  value = value * 8 + current() - '0';
4350  Advance();
4351  }
4352  }
4353  return value;
4354 }
4355 
4356 
4357 bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
4358  int start = position();
4359  uc32 val = 0;
4360  bool done = false;
4361  for (int i = 0; !done; i++) {
4362  uc32 c = current();
4363  int d = HexValue(c);
4364  if (d < 0) {
4365  Reset(start);
4366  return false;
4367  }
4368  val = val * 16 + d;
4369  Advance();
4370  if (i == length - 1) {
4371  done = true;
4372  }
4373  }
4374  *value = val;
4375  return true;
4376 }
4377 
4378 
4379 uc32 RegExpParser::ParseClassCharacterEscape() {
4380  ASSERT(current() == '\\');
4381  ASSERT(has_next() && !IsSpecialClassEscape(Next()));
4382  Advance();
4383  switch (current()) {
4384  case 'b':
4385  Advance();
4386  return '\b';
4387  // ControlEscape :: one of
4388  // f n r t v
4389  case 'f':
4390  Advance();
4391  return '\f';
4392  case 'n':
4393  Advance();
4394  return '\n';
4395  case 'r':
4396  Advance();
4397  return '\r';
4398  case 't':
4399  Advance();
4400  return '\t';
4401  case 'v':
4402  Advance();
4403  return '\v';
4404  case 'c': {
4405  uc32 controlLetter = Next();
4406  uc32 letter = controlLetter & ~('A' ^ 'a');
4407  // For compatibility with JSC, inside a character class
4408  // we also accept digits and underscore as control characters.
4409  if ((controlLetter >= '0' && controlLetter <= '9') ||
4410  controlLetter == '_' ||
4411  (letter >= 'A' && letter <= 'Z')) {
4412  Advance(2);
4413  // Control letters mapped to ASCII control characters in the range
4414  // 0x00-0x1f.
4415  return controlLetter & 0x1f;
4416  }
4417  // We match JSC in reading the backslash as a literal
4418  // character instead of as starting an escape.
4419  return '\\';
4420  }
4421  case '0': case '1': case '2': case '3': case '4': case '5':
4422  case '6': case '7':
4423  // For compatibility, we interpret a decimal escape that isn't
4424  // a back reference (and therefore either \0 or not valid according
4425  // to the specification) as a 1..3 digit octal character code.
4426  return ParseOctalLiteral();
4427  case 'x': {
4428  Advance();
4429  uc32 value;
4430  if (ParseHexEscape(2, &value)) {
4431  return value;
4432  }
4433  // If \x is not followed by a two-digit hexadecimal, treat it
4434  // as an identity escape.
4435  return 'x';
4436  }
4437  case 'u': {
4438  Advance();
4439  uc32 value;
4440  if (ParseHexEscape(4, &value)) {
4441  return value;
4442  }
4443  // If \u is not followed by a four-digit hexadecimal, treat it
4444  // as an identity escape.
4445  return 'u';
4446  }
4447  default: {
4448  // Extended identity escape. We accept any character that hasn't
4449  // been matched by a more specific case, not just the subset required
4450  // by the ECMAScript specification.
4451  uc32 result = current();
4452  Advance();
4453  return result;
4454  }
4455  }
4456  return 0;
4457 }
4458 
4459 
4460 CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4461  ASSERT_EQ(0, *char_class);
4462  uc32 first = current();
4463  if (first == '\\') {
4464  switch (Next()) {
4465  case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4466  *char_class = Next();
4467  Advance(2);
4468  return CharacterRange::Singleton(0); // Return dummy value.
4469  }
4470  case kEndMarker:
4471  return ReportError(CStrVector("\\ at end of pattern"));
4472  default:
4473  uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4474  return CharacterRange::Singleton(c);
4475  }
4476  } else {
4477  Advance();
4478  return CharacterRange::Singleton(first);
4479  }
4480 }
4481 
4482 
4483 static const uc16 kNoCharClass = 0;
4484 
4485 // Adds range or pre-defined character class to character ranges.
4486 // If char_class is not kInvalidClass, it's interpreted as a class
4487 // escape (i.e., 's' means whitespace, from '\s').
4488 static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
4489  uc16 char_class,
4490  CharacterRange range,
4491  Zone* zone) {
4492  if (char_class != kNoCharClass) {
4493  CharacterRange::AddClassEscape(char_class, ranges, zone);
4494  } else {
4495  ranges->Add(range, zone);
4496  }
4497 }
4498 
4499 
4500 RegExpTree* RegExpParser::ParseCharacterClass() {
4501  static const char* kUnterminated = "Unterminated character class";
4502  static const char* kRangeOutOfOrder = "Range out of order in character class";
4503 
4504  ASSERT_EQ(current(), '[');
4505  Advance();
4506  bool is_negated = false;
4507  if (current() == '^') {
4508  is_negated = true;
4509  Advance();
4510  }
4511  ZoneList<CharacterRange>* ranges =
4512  new(zone()) ZoneList<CharacterRange>(2, zone());
4513  while (has_more() && current() != ']') {
4514  uc16 char_class = kNoCharClass;
4515  CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
4516  if (current() == '-') {
4517  Advance();
4518  if (current() == kEndMarker) {
4519  // If we reach the end we break out of the loop and let the
4520  // following code report an error.
4521  break;
4522  } else if (current() == ']') {
4523  AddRangeOrEscape(ranges, char_class, first, zone());
4524  ranges->Add(CharacterRange::Singleton('-'), zone());
4525  break;
4526  }
4527  uc16 char_class_2 = kNoCharClass;
4528  CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
4529  if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
4530  // Either end is an escaped character class. Treat the '-' verbatim.
4531  AddRangeOrEscape(ranges, char_class, first, zone());
4532  ranges->Add(CharacterRange::Singleton('-'), zone());
4533  AddRangeOrEscape(ranges, char_class_2, next, zone());
4534  continue;
4535  }
4536  if (first.from() > next.to()) {
4537  return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
4538  }
4539  ranges->Add(CharacterRange::Range(first.from(), next.to()), zone());
4540  } else {
4541  AddRangeOrEscape(ranges, char_class, first, zone());
4542  }
4543  }
4544  if (!has_more()) {
4545  return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
4546  }
4547  Advance();
4548  if (ranges->length() == 0) {
4549  ranges->Add(CharacterRange::Everything(), zone());
4550  is_negated = !is_negated;
4551  }
4552  return new(zone()) RegExpCharacterClass(ranges, is_negated);
4553 }
4554 
4555 
4556 // ----------------------------------------------------------------------------
4557 // The Parser interface.
4558 
4560  if (owns_store_) store_.Dispose();
4561 }
4562 
4563 
4565  return store_.length() * sizeof(unsigned);
4566 }
4567 
4568 
4569 const char* ScriptDataImpl::Data() {
4570  return reinterpret_cast<const char*>(store_.start());
4571 }
4572 
4573 
4575  return has_error();
4576 }
4577 
4578 
4580  // Prepares state for use.
4581  if (store_.length() >= PreparseDataConstants::kHeaderSize) {
4582  function_index_ = PreparseDataConstants::kHeaderSize;
4583  int symbol_data_offset = PreparseDataConstants::kHeaderSize
4585  if (store_.length() > symbol_data_offset) {
4586  symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
4587  } else {
4588  // Partial preparse causes no symbol information.
4589  symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
4590  }
4591  symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
4592  }
4593 }
4594 
4595 
4596 int ScriptDataImpl::ReadNumber(byte** source) {
4597  // Reads a number from symbol_data_ in base 128. The most significant
4598  // bit marks that there are more digits.
4599  // If the first byte is 0x80 (kNumberTerminator), it would normally
4600  // represent a leading zero. Since that is useless, and therefore won't
4601  // appear as the first digit of any actual value, it is used to
4602  // mark the end of the input stream.
4603  byte* data = *source;
4604  if (data >= symbol_data_end_) return -1;
4605  byte input = *data;
4607  // End of stream marker.
4608  return -1;
4609  }
4610  int result = input & 0x7f;
4611  data++;
4612  while ((input & 0x80u) != 0) {
4613  if (data >= symbol_data_end_) return -1;
4614  input = *data;
4615  result = (result << 7) | (input & 0x7f);
4616  data++;
4617  }
4618  *source = data;
4619  return result;
4620 }
4621 
4622 
4623 // Create a Scanner for the preparser to use as input, and preparse the source.
4625  Utf16CharacterStream* source) {
4626  CompleteParserRecorder recorder;
4627  HistogramTimerScope timer(isolate->counters()->pre_parse());
4628  Scanner scanner(isolate->unicode_cache());
4629  intptr_t stack_limit = isolate->stack_guard()->real_climit();
4630  PreParser preparser(&scanner, &recorder, stack_limit);
4631  preparser.set_allow_lazy(true);
4632  preparser.set_allow_generators(FLAG_harmony_generators);
4633  preparser.set_allow_for_of(FLAG_harmony_iteration);
4634  preparser.set_allow_harmony_scoping(FLAG_harmony_scoping);
4635  preparser.set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
4636  scanner.Initialize(source);
4637  PreParser::PreParseResult result = preparser.PreParseProgram();
4638  if (result == PreParser::kPreParseStackOverflow) {
4639  isolate->StackOverflow();
4640  return NULL;
4641  }
4642 
4643  // Extract the accumulated data from the recorder as a single
4644  // contiguous vector that we are responsible for disposing.
4645  Vector<unsigned> store = recorder.ExtractData();
4646  return new ScriptDataImpl(store);
4647 }
4648 
4649 
4650 bool RegExpParser::ParseRegExp(FlatStringReader* input,
4651  bool multiline,
4652  RegExpCompileData* result,
4653  Zone* zone) {
4654  ASSERT(result != NULL);
4655  RegExpParser parser(input, &result->error, multiline, zone);
4656  RegExpTree* tree = parser.ParsePattern();
4657  if (parser.failed()) {
4658  ASSERT(tree == NULL);
4659  ASSERT(!result->error.is_null());
4660  } else {
4661  ASSERT(tree != NULL);
4662  ASSERT(result->error.is_null());
4663  result->tree = tree;
4664  int capture_count = parser.captures_started();
4665  result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
4666  result->contains_anchor = parser.contains_anchor();
4667  result->capture_count = capture_count;
4668  }
4669  return !parser.failed();
4670 }
4671 
4672 
4674  ASSERT(info()->function() == NULL);
4675  FunctionLiteral* result = NULL;
4676  if (info()->is_lazy()) {
4677  ASSERT(!info()->is_eval());
4678  if (info()->shared_info()->is_function()) {
4679  result = ParseLazy();
4680  } else {
4681  result = ParseProgram();
4682  }
4683  } else {
4684  SetCachedData(info()->cached_data(), info()->cached_data_mode());
4685  if (info()->cached_data_mode() == CONSUME_CACHED_DATA &&
4686  (*info()->cached_data())->has_error()) {
4687  ScriptDataImpl* cached_data = *(info()->cached_data());
4688  Scanner::Location loc = cached_data->MessageLocation();
4689  const char* message = cached_data->BuildMessage();
4690  Vector<const char*> args = cached_data->BuildArgs();
4691  ParserTraits::ReportMessageAt(loc, message, args);
4692  DeleteArray(message);
4693  for (int i = 0; i < args.length(); i++) {
4694  DeleteArray(args[i]);
4695  }
4696  DeleteArray(args.start());
4697  ASSERT(info()->isolate()->has_pending_exception());
4698  } else {
4699  result = ParseProgram();
4700  }
4701  }
4702  info()->SetFunction(result);
4703  return (result != NULL);
4704 }
4705 
4706 } } // namespace v8::internal
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
RegExpTree * ToRegExp()
Definition: parser.cc:148
Scope * DeclarationScope()
Definition: scopes.cc:743
Failure * StackOverflow()
Definition: isolate.cc:871
virtual bool IsTextElement()
Definition: ast.h:2507
PreParseResult PreParseProgram()
Definition: preparser.h:1021
Vector< const char * > BuildArgs()
Definition: parser.cc:320
void PushVariableName(Handle< String > name)
uint16_t current_
ExpressionT ParseExpression(bool accept_IN, bool *ok)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths true
Definition: flags.cc:208
void PrintF(const char *format,...)
Definition: v8utils.cc:40
Expression * BuildUnaryExpression(Expression *expression, Token::Value op, int pos, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:556
static Interface * NewModule(Zone *zone)
Definition: interface.h:76
static String * cast(Object *obj)
Variable * receiver()
Definition: scopes.h:322
Local< Value > Get(Handle< Value > key)
Definition: api.cc:3139
static Expression * MarkExpressionAsLValue(Expression *expression)
Definition: parser.cc:474
static Smi * FromInt(int value)
Definition: objects-inl.h:1209
static const Function * FunctionForName(Handle< String > name)
Definition: runtime.cc:15142
Vector< const T > ToConstVector()
Definition: list.h:104
void CheckOctalLiteral(int beg_pos, int end_pos, bool *ok)
Definition: preparser.h:349
ParserTraits::Type::Zone * zone() const
Definition: preparser.h:260
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
void AddQuantifierToAtom(int min, int max, RegExpQuantifier::QuantifierType type)
Definition: parser.cc:161
void CheckStrictModeLValue(Expression *expression, bool *ok)
Definition: parser.cc:483
static Handle< FixedArray > GetElements(Handle< FixedArray > value)
Definition: parser.cc:3128
int32_t uc32
Definition: globals.h:310
Handle< String > NextLiteralString(Scanner *scanner, PretenureFlag tenured)
Definition: parser.cc:684
static void CheckAssigningFunctionLiteralToProperty(Expression *left, Expression *right)
Definition: parser.cc:454
Expression * ExpressionFromString(int pos, Scanner *scanner, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:734
void set_allow_harmony_numeric_literals(bool allow)
Definition: preparser.h:132
Vector< T > SubVector(int from, int to)
Definition: utils.h:412
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage message
Definition: flags.cc:665
Handle< JSArray > NewJSArrayWithElements(Handle< FixedArrayBase > elements, ElementsKind elements_kind, int length, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:1456
VariableProxy * NewUnresolved(AstNodeFactory< Visitor > *factory, Handle< String > name, Interface *interface=Interface::NewValue(), int position=RelocInfo::kNoPosition)
Definition: scopes.h:167
bool Check(Token::Value token)
Definition: preparser.h:288
void ReportUnexpectedToken(Token::Value token)
static CharacterRange Everything()
Definition: jsregexp.h:274
void AddAtom(RegExpTree *tree)
Definition: parser.cc:103
uintptr_t real_climit()
Definition: execution.h:241
static const Function * FunctionForId(FunctionId id)
Definition: runtime.cc:15154
#define ASSERT(condition)
Definition: checks.h:329
void ForceEagerCompilation()
Definition: scopes.h:381
ExpressionT ParseAssignmentExpression(bool accept_IN, bool *ok)
static bool IsCompileTimeValue(Expression *expression)
Definition: parser.cc:3090
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including on console Map counters to a file Enable debugger compile events enable GDBJIT interface(disables compacting GC)") DEFINE_bool(gdbjit_full
virtual MaterializedLiteral * AsMaterializedLiteral()
Definition: ast.h:227
void Consume(Token::Value token)
Definition: preparser.h:281
ParserTraits::Type::Scope * scope_
Definition: preparser.h:488
Factory * factory()
Definition: isolate.h:995
IdentifierT ParseIdentifierOrStrictReservedWord(bool *is_strict_reserved, bool *ok)
bool Equals(Handle< Value > that) const
Definition: api.cc:2950
void ReportMessageAt(Scanner::Location source_location, const char *message, Vector< const char * > args, bool is_reference_error=false)
Definition: parser.cc:602
#define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value)
Definition: isolate.h:137
static Smi * cast(Object *object)
Literal * GetLiteralTheHole(int position, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:743
StackGuard * stack_guard()
Definition: isolate.h:874
FunctionEntry GetFunctionEntry(int start)
Definition: parser.cc:227
bool stack_overflow() const
Definition: preparser.h:257
uint8_t byte
Definition: globals.h:185
Literal * ExpressionFromLiteral(Token::Value token, int pos, Scanner *scanner, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:697
static Interface * NewValue()
Definition: interface.h:66
Handle< String > NewStringFromUtf8(Vector< const char > str, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:273
UnicodeCache * unicode_cache()
Definition: isolate.h:908
#define IN
void AddAssertion(RegExpTree *tree)
Definition: parser.cc:119
void ReportMessageAt(Scanner::Location location, const char *message, bool is_reference_error=false)
Definition: preparser.h:380
#define UNREACHABLE()
Definition: checks.h:52
static Interface * NewUnknown(Zone *zone)
Definition: interface.h:62
T * start() const
Definition: utils.h:426
Handle< Object > NewReferenceError(const char *message, Vector< Handle< Object > > args)
Definition: factory.cc:1072
bool literal_contains_escapes() const
Definition: scanner.h:384
IdentifierT ParseIdentifierName(bool *ok)
static CharacterRange Range(uc16 from, uc16 to)
Definition: jsregexp.h:270
static LiteralType GetLiteralType(Handle< FixedArray > value)
Definition: parser.cc:3121
static const int kInfinity
Definition: ast.h:2502
#define CHECK_OK
Definition: parser.cc:405
void check(i::Vector< const uint8_t > string)
#define CHECK_FAILED
Definition: parser.cc:411
static bool IsIdentifier(Expression *expression)
Definition: parser.cc:437
void ExpectContextualKeyword(Vector< const char > keyword, bool *ok)
Definition: preparser.h:338
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array shift
Definition: flags.cc:211
Handle< Object > ToBoolean(bool value)
Definition: factory.cc:2022
void ReportMessage(const char *message, Vector< const char * > args, bool is_reference_error=false)
Definition: preparser.h:374
void SeekForward(int pos)
Definition: scanner.cc:601
int HexValue(uc32 c)
Definition: scanner.h:52
Handle< FixedArray > NewFixedArray(int size, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:53
bool IsLexicalVariableMode(VariableMode mode)
Definition: v8globals.h:508
bool IsEvalOrArguments(Handle< String > identifier) const
Definition: parser.cc:420
static Handle< FixedArray > GetValue(Isolate *isolate, Expression *expression)
Definition: parser.cc:3097
Handle< String > GetSymbol(Scanner *scanner=NULL)
Definition: parser.cc:664
int length() const
Definition: utils.h:420
TargetScope(Target **variable)
Definition: parser.cc:382
bool CheckContextualKeyword(Vector< const char > keyword)
Definition: preparser.h:329
bool BooleanValue() const
Definition: api.cc:2824
#define COMMA
Definition: flags.h:101
Failure * Throw(Object *exception, MessageLocation *location=NULL)
Definition: isolate.cc:923
#define STATIC_ASCII_VECTOR(x)
Definition: utils.h:570
#define BASE_EMBEDDED
Definition: allocation.h:68
#define LAST(x)
Definition: parser.h:277
virtual bool IsPropertyName()
Definition: ast.h:337
bool IsDeclaredVariableMode(VariableMode mode)
Definition: v8globals.h:503
virtual void LogFunction(int start, int end, int literals, int properties, StrictMode strict_mode)=0
void Initialize(Utf16CharacterStream *source)
Definition: scanner.cc:55
Vector< const char > CStrVector(const char *data)
Definition: utils.h:574
static ScriptDataImpl * PreParse(Isolate *isolate, Utf16CharacterStream *source)
Definition: parser.cc:4624
bool ShortcutNumericLiteralBinaryExpression(Expression **x, Expression *y, Token::Value op, int pos, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:496
void ReportMessage(const char *message, Vector< Handle< String > > args, bool is_reference_error=false)
Definition: parser.cc:630
const char * BuildMessage()
Definition: parser.cc:314
static Location invalid()
Definition: scanner.h:356
static Interface * NewConst()
Definition: interface.h:71
V8_INLINE bool IsString() const
Definition: v8.h:6265
void PushEnclosingName(Handle< String > name)
int ArithmeticShiftRight(int x, int s)
Definition: utils.h:111
uint32_t DoubleToUint32(double x)
Definition: conversions.h:106
Handle< Object > NewSyntaxError(const char *message, Handle< JSArray > args)
Definition: factory.cc:1061
void PushLiteralName(Handle< String > name)
int32_t DoubleToInt32(double x)
Expression * ThisExpression(Scope *scope, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:690
#define CASE(name)
Location location() const
Definition: scanner.h:375
PreParseResult PreParseLazyFunction(StrictMode strict_mode, bool is_generator, ParserRecorder *log)
Definition: preparser.cc:149
Handle< String > InternalizeOneByteString(Vector< const uint8_t > str)
Definition: factory.cc:232
bool is_null() const
Definition: handles.h:81
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
Definition: flags.cc:317
virtual const char * Data()
Definition: parser.cc:4569
bool IsNumber() const
Definition: api.cc:2416
Target(Target **variable, AstNode *node)
Definition: parser.cc:361
static bool IsThisProperty(Expression *expression)
Definition: parser.cc:428
void AddCharacter(uc16 character)
Definition: parser.cc:88
uint16_t uc16
Definition: globals.h:309
Scanner::Location MessageLocation()
Definition: parser.cc:307
void LogSymbol(ParserRecorder *log, int position)
Definition: scanner.cc:1163
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
void Add(Handle< String > name, Interface *interface, Zone *zone, bool *ok)
Definition: interface.h:85
static const unsigned char kNumberTerminator
static Handle< T > null()
Definition: handles.h:80
void PushPropertyName(FuncNameInferrer *fni, Expression *expression)
Definition: parser.cc:443
#define ASSERT_EQ(v1, v2)
Definition: checks.h:330
void USE(T)
Definition: globals.h:341
Counters * counters()
Definition: isolate.h:859
#define ASSERT_NE(v1, v2)
Definition: checks.h:331
FuncNameInferrer * fni_
Definition: preparser.h:491
static FixedArray * cast(Object *obj)
Handle< String > AllocateNextLiteralString(Isolate *isolate, PretenureFlag tenured)
Definition: scanner.cc:1119
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:39
static const int kMaxArguments
Definition: objects.h:5681
void AddFunction(FunctionLiteral *func_to_infer)
ZoneList< Handle< String > > ZoneStringList
Definition: ast.h:161
void RecordEvalCall()
Definition: scopes.h:234
Handle< String > NewConsString(Handle< String > left, Handle< String > right)
Definition: factory.cc:370
FunctionLiteral * ParseFunctionLiteral(Handle< String > name, Scanner::Location function_name_location, bool name_is_strict_reserved, bool is_generator, int function_token_position, FunctionLiteral::FunctionType type, bool *ok)
Definition: parser.cc:755
void DeleteArray(T *array)
Definition: allocation.h:91
ParserTraits::Type::ExpressionList ParseArguments(bool *ok)
virtual int max_match()=0
void Expect(Token::Value token, bool *ok)
Definition: preparser.h:297
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
RegExpBuilder(Zone *zone)
Definition: parser.cc:48
Handle< String > AllocateInternalizedString(Isolate *isolate)
Definition: scanner.cc:1131
static Scope * DeserializeScopeChain(Context *context, Scope *global_scope, Zone *zone)
Definition: scopes.cc:214
#define ARRAY_SIZE(a)
Definition: globals.h:333
IdentifierT ParseIdentifier(AllowEvalOrArgumentsAsIdentifier, bool *ok)
static const char *const kStackOverflowMessage
Definition: isolate.h:822
Parser(CompilationInfo *info)
Definition: parser.cc:769
static void AddClassEscape(uc16 type, ZoneList< CharacterRange > *ranges, Zone *zone)
Definition: jsregexp.cc:5199
bool IsDecimalDigit(uc32 c)
virtual bool HasError()
Definition: parser.cc:4574
Expression * ParseV8Intrinsic(bool *ok)
Definition: parser.cc:750
static CharacterRange Singleton(uc16 value)
Definition: jsregexp.h:267
ParserTraits::Type::Factory * factory()
Definition: preparser.h:366
Location peek_location() const
Definition: scanner.h:382
void CheckPossibleEvalCall(Expression *expression, Scope *scope)
Definition: parser.cc:464
Expression * ExpressionFromIdentifier(Handle< String > name, int pos, Scope *scope, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:720
ParserRecorder * log_
Definition: preparser.h:492