blob: 51036c9f3ef761bb8475f8e9050345d5f34faee7 [file] [log] [blame]
Ben Murdoch8b112d22011-06-08 16:22:53 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// 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"
Ben Murdoch592a9fc2012-03-05 11:04:45 +000031#include "ast.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000032#include "bootstrapper.h"
Ben Murdoch589d6972011-11-30 16:04:58 +000033#include "char-predicates-inl.h"
Steve Block6ded16b2010-05-10 14:33:55 +010034#include "codegen.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035#include "compiler.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010036#include "func-name-inferrer.h"
Steve Block6ded16b2010-05-10 14:33:55 +010037#include "messages.h"
Kristian Monsen25f61362010-05-21 11:50:48 +010038#include "parser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000039#include "platform.h"
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080040#include "preparser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000041#include "runtime.h"
Ben Murdoch589d6972011-11-30 16:04:58 +000042#include "scanner-character-streams.h"
Ben Murdoch3bec4d22010-07-22 14:51:16 +010043#include "scopeinfo.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000044#include "string-stream.h"
45
46namespace v8 {
47namespace internal {
48
Steve Blocka7e24c12009-10-30 11:49:00 +000049// PositionStack is used for on-stack allocation of token positions for
50// new expressions. Please look at ParseNewExpression.
51
52class PositionStack {
53 public:
54 explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
55 ~PositionStack() { ASSERT(!*ok_ || is_empty()); }
56
57 class Element {
58 public:
59 Element(PositionStack* stack, int value) {
60 previous_ = stack->top();
61 value_ = value;
62 stack->set_top(this);
63 }
64
65 private:
66 Element* previous() { return previous_; }
67 int value() { return value_; }
68 friend class PositionStack;
69 Element* previous_;
70 int value_;
71 };
72
73 bool is_empty() { return top_ == NULL; }
74 int pop() {
75 ASSERT(!is_empty());
76 int result = top_->value();
77 top_ = top_->previous();
78 return result;
79 }
80
81 private:
82 Element* top() { return top_; }
83 void set_top(Element* value) { top_ = value; }
84 Element* top_;
85 bool* ok_;
86};
87
88
Steve Blocka7e24c12009-10-30 11:49:00 +000089RegExpBuilder::RegExpBuilder()
Ben Murdoch8b112d22011-06-08 16:22:53 +010090 : zone_(Isolate::Current()->zone()),
91 pending_empty_(false),
92 characters_(NULL),
93 terms_(),
94 alternatives_()
Steve Blocka7e24c12009-10-30 11:49:00 +000095#ifdef DEBUG
Ben Murdoch8b112d22011-06-08 16:22:53 +010096 , last_added_(ADD_NONE)
Steve Blocka7e24c12009-10-30 11:49:00 +000097#endif
98 {}
99
100
101void RegExpBuilder::FlushCharacters() {
102 pending_empty_ = false;
103 if (characters_ != NULL) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100104 RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector());
Steve Blocka7e24c12009-10-30 11:49:00 +0000105 characters_ = NULL;
106 text_.Add(atom);
107 LAST(ADD_ATOM);
108 }
109}
110
111
112void RegExpBuilder::FlushText() {
113 FlushCharacters();
114 int num_text = text_.length();
115 if (num_text == 0) {
116 return;
117 } else if (num_text == 1) {
118 terms_.Add(text_.last());
119 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100120 RegExpText* text = new(zone()) RegExpText();
Steve Blocka7e24c12009-10-30 11:49:00 +0000121 for (int i = 0; i < num_text; i++)
122 text_.Get(i)->AppendToText(text);
123 terms_.Add(text);
124 }
125 text_.Clear();
126}
127
128
129void RegExpBuilder::AddCharacter(uc16 c) {
130 pending_empty_ = false;
131 if (characters_ == NULL) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000132 characters_ = new(zone()) ZoneList<uc16>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000133 }
134 characters_->Add(c);
135 LAST(ADD_CHAR);
136}
137
138
139void RegExpBuilder::AddEmpty() {
140 pending_empty_ = true;
141}
142
143
144void RegExpBuilder::AddAtom(RegExpTree* term) {
145 if (term->IsEmpty()) {
146 AddEmpty();
147 return;
148 }
149 if (term->IsTextElement()) {
150 FlushCharacters();
151 text_.Add(term);
152 } else {
153 FlushText();
154 terms_.Add(term);
155 }
156 LAST(ADD_ATOM);
157}
158
159
160void RegExpBuilder::AddAssertion(RegExpTree* assert) {
161 FlushText();
162 terms_.Add(assert);
163 LAST(ADD_ASSERT);
164}
165
166
167void RegExpBuilder::NewAlternative() {
168 FlushTerms();
169}
170
171
172void RegExpBuilder::FlushTerms() {
173 FlushText();
174 int num_terms = terms_.length();
175 RegExpTree* alternative;
176 if (num_terms == 0) {
177 alternative = RegExpEmpty::GetInstance();
178 } else if (num_terms == 1) {
179 alternative = terms_.last();
180 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100181 alternative = new(zone()) RegExpAlternative(terms_.GetList());
Steve Blocka7e24c12009-10-30 11:49:00 +0000182 }
183 alternatives_.Add(alternative);
184 terms_.Clear();
185 LAST(ADD_NONE);
186}
187
188
189RegExpTree* RegExpBuilder::ToRegExp() {
190 FlushTerms();
191 int num_alternatives = alternatives_.length();
192 if (num_alternatives == 0) {
193 return RegExpEmpty::GetInstance();
194 }
195 if (num_alternatives == 1) {
196 return alternatives_.last();
197 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100198 return new(zone()) RegExpDisjunction(alternatives_.GetList());
Steve Blocka7e24c12009-10-30 11:49:00 +0000199}
200
201
Leon Clarkee46be812010-01-19 14:06:41 +0000202void RegExpBuilder::AddQuantifierToAtom(int min,
203 int max,
204 RegExpQuantifier::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000205 if (pending_empty_) {
206 pending_empty_ = false;
207 return;
208 }
209 RegExpTree* atom;
210 if (characters_ != NULL) {
211 ASSERT(last_added_ == ADD_CHAR);
212 // Last atom was character.
213 Vector<const uc16> char_vector = characters_->ToConstVector();
214 int num_chars = char_vector.length();
215 if (num_chars > 1) {
216 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100217 text_.Add(new(zone()) RegExpAtom(prefix));
Steve Blocka7e24c12009-10-30 11:49:00 +0000218 char_vector = char_vector.SubVector(num_chars - 1, num_chars);
219 }
220 characters_ = NULL;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100221 atom = new(zone()) RegExpAtom(char_vector);
Steve Blocka7e24c12009-10-30 11:49:00 +0000222 FlushText();
223 } else if (text_.length() > 0) {
224 ASSERT(last_added_ == ADD_ATOM);
225 atom = text_.RemoveLast();
226 FlushText();
227 } else if (terms_.length() > 0) {
228 ASSERT(last_added_ == ADD_ATOM);
229 atom = terms_.RemoveLast();
230 if (atom->max_match() == 0) {
231 // Guaranteed to only match an empty string.
232 LAST(ADD_TERM);
233 if (min == 0) {
234 return;
235 }
236 terms_.Add(atom);
237 return;
238 }
239 } else {
240 // Only call immediately after adding an atom or character!
241 UNREACHABLE();
242 return;
243 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100244 terms_.Add(new(zone()) RegExpQuantifier(min, max, type, atom));
Steve Blocka7e24c12009-10-30 11:49:00 +0000245 LAST(ADD_TERM);
246}
247
248
Steve Block9fac8402011-05-12 15:51:54 +0100249Handle<String> Parser::LookupSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800250 // Length of symbol cache is the number of identified symbols.
251 // If we are larger than that, or negative, it's not a cached symbol.
252 // This might also happen if there is no preparser symbol data, even
253 // if there is some preparser data.
254 if (static_cast<unsigned>(symbol_id)
255 >= static_cast<unsigned>(symbol_cache_.length())) {
Steve Block9fac8402011-05-12 15:51:54 +0100256 if (scanner().is_literal_ascii()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100257 return isolate()->factory()->LookupAsciiSymbol(
258 scanner().literal_ascii_string());
Steve Block9fac8402011-05-12 15:51:54 +0100259 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100260 return isolate()->factory()->LookupTwoByteSymbol(
261 scanner().literal_uc16_string());
Steve Block9fac8402011-05-12 15:51:54 +0100262 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800263 }
Steve Block9fac8402011-05-12 15:51:54 +0100264 return LookupCachedSymbol(symbol_id);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800265}
266
267
Steve Block9fac8402011-05-12 15:51:54 +0100268Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800269 // Make sure the cache is large enough to hold the symbol identifier.
270 if (symbol_cache_.length() <= symbol_id) {
271 // Increase length to index + 1.
272 symbol_cache_.AddBlock(Handle<String>::null(),
273 symbol_id + 1 - symbol_cache_.length());
274 }
275 Handle<String> result = symbol_cache_.at(symbol_id);
276 if (result.is_null()) {
Steve Block9fac8402011-05-12 15:51:54 +0100277 if (scanner().is_literal_ascii()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100278 result = isolate()->factory()->LookupAsciiSymbol(
279 scanner().literal_ascii_string());
Steve Block9fac8402011-05-12 15:51:54 +0100280 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100281 result = isolate()->factory()->LookupTwoByteSymbol(
282 scanner().literal_uc16_string());
Steve Block9fac8402011-05-12 15:51:54 +0100283 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800284 symbol_cache_.at(symbol_id) = result;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100285 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000286 }
Steve Block44f0eee2011-05-26 01:26:41 +0100287 isolate()->counters()->total_preparse_symbols_skipped()->Increment();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800288 return result;
289}
Steve Blocka7e24c12009-10-30 11:49:00 +0000290
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800291
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100292FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
293 // The current pre-data entry must be a FunctionEntry with the given
294 // start position.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100295 if ((function_index_ + FunctionEntry::kSize <= store_.length())
296 && (static_cast<int>(store_[function_index_]) == start)) {
297 int index = function_index_;
298 function_index_ += FunctionEntry::kSize;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100299 return FunctionEntry(store_.SubVector(index,
300 index + FunctionEntry::kSize));
Steve Blocka7e24c12009-10-30 11:49:00 +0000301 }
302 return FunctionEntry();
303}
304
305
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100306int ScriptDataImpl::GetSymbolIdentifier() {
307 return ReadNumber(&symbol_data_);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100308}
309
310
Iain Merrick9ac36c92010-09-13 15:29:50 +0100311bool ScriptDataImpl::SanityCheck() {
312 // Check that the header data is valid and doesn't specify
313 // point to positions outside the store.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800314 if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
315 if (magic() != PreparseDataConstants::kMagicNumber) return false;
316 if (version() != PreparseDataConstants::kCurrentVersion) return false;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100317 if (has_error()) {
318 // Extra sane sanity check for error message encoding.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800319 if (store_.length() <= PreparseDataConstants::kHeaderSize
320 + PreparseDataConstants::kMessageTextPos) {
321 return false;
322 }
323 if (Read(PreparseDataConstants::kMessageStartPos) >
324 Read(PreparseDataConstants::kMessageEndPos)) {
325 return false;
326 }
327 unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
328 int pos = PreparseDataConstants::kMessageTextPos;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100329 for (unsigned int i = 0; i <= arg_count; i++) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800330 if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
331 return false;
332 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100333 int length = static_cast<int>(Read(pos));
334 if (length < 0) return false;
335 pos += 1 + length;
336 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800337 if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
338 return false;
339 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100340 return true;
341 }
342 // Check that the space allocated for function entries is sane.
343 int functions_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800344 static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100345 if (functions_size < 0) return false;
346 if (functions_size % FunctionEntry::kSize != 0) return false;
347 // Check that the count of symbols is non-negative.
348 int symbol_count =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800349 static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100350 if (symbol_count < 0) return false;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100351 // Check that the total size has room for header and function entries.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100352 int minimum_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800353 PreparseDataConstants::kHeaderSize + functions_size;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100354 if (store_.length() < minimum_size) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000355 return true;
356}
357
358
Steve Block59151502010-09-22 15:07:15 +0100359
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100360const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000361 int length = start[0];
362 char* result = NewArray<char>(length + 1);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100363 for (int i = 0; i < length; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000364 result[i] = start[i + 1];
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100365 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000366 result[length] = '\0';
367 if (chars != NULL) *chars = length;
368 return result;
369}
370
Steve Blocka7e24c12009-10-30 11:49:00 +0000371Scanner::Location ScriptDataImpl::MessageLocation() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800372 int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
373 int end_pos = Read(PreparseDataConstants::kMessageEndPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000374 return Scanner::Location(beg_pos, end_pos);
375}
376
377
378const char* ScriptDataImpl::BuildMessage() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800379 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100380 return ReadString(start, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000381}
382
383
384Vector<const char*> ScriptDataImpl::BuildArgs() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800385 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000386 const char** array = NewArray<const char*>(arg_count);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100387 // Position after text found by skipping past length field and
388 // length field content words.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800389 int pos = PreparseDataConstants::kMessageTextPos + 1
390 + Read(PreparseDataConstants::kMessageTextPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 for (int i = 0; i < arg_count; i++) {
392 int count = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100393 array[i] = ReadString(ReadAddress(pos), &count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000394 pos += count + 1;
395 }
396 return Vector<const char*>(array, arg_count);
397}
398
399
400unsigned ScriptDataImpl::Read(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800401 return store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000402}
403
404
405unsigned* ScriptDataImpl::ReadAddress(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800406 return &store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000407}
408
409
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000410Scope* Parser::NewScope(Scope* parent, ScopeType type) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100411 Scope* result = new(zone()) Scope(parent, type);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000412 result->Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 return result;
414}
415
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000416
Steve Blocka7e24c12009-10-30 11:49:00 +0000417// ----------------------------------------------------------------------------
418// Target is a support class to facilitate manipulation of the
419// Parser's target_stack_ (the stack of potential 'break' and
420// 'continue' statement targets). Upon construction, a new target is
421// added; it is removed upon destruction.
422
423class Target BASE_EMBEDDED {
424 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800425 Target(Target** variable, AstNode* node)
426 : variable_(variable), node_(node), previous_(*variable) {
427 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000428 }
429
430 ~Target() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800431 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000432 }
433
434 Target* previous() { return previous_; }
435 AstNode* node() { return node_; }
436
437 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800438 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000439 AstNode* node_;
440 Target* previous_;
441};
442
443
444class TargetScope BASE_EMBEDDED {
445 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800446 explicit TargetScope(Target** variable)
447 : variable_(variable), previous_(*variable) {
448 *variable = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000449 }
450
451 ~TargetScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800452 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000453 }
454
455 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800456 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000457 Target* previous_;
458};
459
460
461// ----------------------------------------------------------------------------
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000462// FunctionState and BlockState together implement the parser's scope stack.
463// The parser's current scope is in top_scope_. The BlockState and
464// FunctionState constructors push on the scope stack and the destructors
465// pop. They are also used to hold the parser's per-function and per-block
466// state.
Steve Blocka7e24c12009-10-30 11:49:00 +0000467
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000468class Parser::BlockState BASE_EMBEDDED {
Steve Blocka7e24c12009-10-30 11:49:00 +0000469 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000470 BlockState(Parser* parser, Scope* scope)
471 : parser_(parser),
472 outer_scope_(parser->top_scope_) {
473 parser->top_scope_ = scope;
474 }
475
476 ~BlockState() { parser_->top_scope_ = outer_scope_; }
477
478 private:
479 Parser* parser_;
480 Scope* outer_scope_;
481};
482
483
484class Parser::FunctionState BASE_EMBEDDED {
485 public:
486 FunctionState(Parser* parser, Scope* scope, Isolate* isolate);
487 ~FunctionState();
Steve Block44f0eee2011-05-26 01:26:41 +0100488
489 int NextMaterializedLiteralIndex() {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000490 return next_materialized_literal_index_++;
Steve Block44f0eee2011-05-26 01:26:41 +0100491 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000492 int materialized_literal_count() {
493 return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
494 }
495
496 int NextHandlerIndex() { return next_handler_index_++; }
497 int handler_count() { return next_handler_index_; }
Steve Block44f0eee2011-05-26 01:26:41 +0100498
499 void SetThisPropertyAssignmentInfo(
500 bool only_simple_this_property_assignments,
501 Handle<FixedArray> this_property_assignments) {
502 only_simple_this_property_assignments_ =
503 only_simple_this_property_assignments;
504 this_property_assignments_ = this_property_assignments;
505 }
506 bool only_simple_this_property_assignments() {
507 return only_simple_this_property_assignments_;
508 }
509 Handle<FixedArray> this_property_assignments() {
510 return this_property_assignments_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000511 }
512
Steve Block44f0eee2011-05-26 01:26:41 +0100513 void AddProperty() { expected_property_count_++; }
514 int expected_property_count() { return expected_property_count_; }
515
Steve Blocka7e24c12009-10-30 11:49:00 +0000516 private:
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000517 // Used to assign an index to each literal that needs materialization in
518 // the function. Includes regexp literals, and boilerplate for object and
519 // array literals.
520 int next_materialized_literal_index_;
521
522 // Used to assign a per-function index to try and catch handlers.
523 int next_handler_index_;
Steve Block44f0eee2011-05-26 01:26:41 +0100524
525 // Properties count estimation.
526 int expected_property_count_;
527
528 // Keeps track of assignments to properties of this. Used for
529 // optimizing constructors.
530 bool only_simple_this_property_assignments_;
531 Handle<FixedArray> this_property_assignments_;
532
Steve Block44f0eee2011-05-26 01:26:41 +0100533 Parser* parser_;
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000534 FunctionState* outer_function_state_;
535 Scope* outer_scope_;
536 unsigned saved_ast_node_id_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000537};
538
Steve Block44f0eee2011-05-26 01:26:41 +0100539
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000540Parser::FunctionState::FunctionState(Parser* parser,
541 Scope* scope,
542 Isolate* isolate)
543 : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
544 next_handler_index_(0),
545 expected_property_count_(0),
546 only_simple_this_property_assignments_(false),
547 this_property_assignments_(isolate->factory()->empty_fixed_array()),
548 parser_(parser),
549 outer_function_state_(parser->current_function_state_),
550 outer_scope_(parser->top_scope_),
551 saved_ast_node_id_(isolate->ast_node_id()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100552 parser->top_scope_ = scope;
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000553 parser->current_function_state_ = this;
Ben Murdoch589d6972011-11-30 16:04:58 +0000554 isolate->set_ast_node_id(AstNode::kDeclarationsId + 1);
Steve Block44f0eee2011-05-26 01:26:41 +0100555}
556
557
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000558Parser::FunctionState::~FunctionState() {
559 parser_->top_scope_ = outer_scope_;
560 parser_->current_function_state_ = outer_function_state_;
561 parser_->isolate()->set_ast_node_id(saved_ast_node_id_);
Steve Block44f0eee2011-05-26 01:26:41 +0100562}
563
564
Steve Blocka7e24c12009-10-30 11:49:00 +0000565// ----------------------------------------------------------------------------
566// The CHECK_OK macro is a convenient macro to enforce error
567// handling for functions that may fail (by returning !*ok).
568//
569// CAUTION: This macro appends extra statements after a call,
570// thus it must never be used where only a single statement
571// is correct (e.g. an if statement branch w/o braces)!
572
573#define CHECK_OK ok); \
574 if (!*ok) return NULL; \
575 ((void)0
576#define DUMMY ) // to make indentation work
577#undef DUMMY
578
579#define CHECK_FAILED /**/); \
580 if (failed_) return NULL; \
581 ((void)0
582#define DUMMY ) // to make indentation work
583#undef DUMMY
584
585// ----------------------------------------------------------------------------
586// Implementation of Parser
587
588Parser::Parser(Handle<Script> script,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000589 int parser_flags,
Steve Blocka7e24c12009-10-30 11:49:00 +0000590 v8::Extension* extension,
Steve Blocka7e24c12009-10-30 11:49:00 +0000591 ScriptDataImpl* pre_data)
Steve Block44f0eee2011-05-26 01:26:41 +0100592 : isolate_(script->GetIsolate()),
593 symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800594 script_(script),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100595 scanner_(isolate_->unicode_cache()),
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000596 reusable_preparser_(NULL),
Steve Blocka7e24c12009-10-30 11:49:00 +0000597 top_scope_(NULL),
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000598 current_function_state_(NULL),
Steve Blocka7e24c12009-10-30 11:49:00 +0000599 target_stack_(NULL),
Steve Blocka7e24c12009-10-30 11:49:00 +0000600 extension_(extension),
Steve Block6ded16b2010-05-10 14:33:55 +0100601 pre_data_(pre_data),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100602 fni_(NULL),
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000603 allow_natives_syntax_((parser_flags & kAllowNativesSyntax) != 0),
604 allow_lazy_((parser_flags & kAllowLazy) != 0),
Ben Murdochb8e0da22011-05-16 14:20:40 +0100605 stack_overflow_(false),
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000606 parenthesized_function_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100607 AstNode::ResetIds();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000608 if ((parser_flags & kLanguageModeMask) == EXTENDED_MODE) {
609 scanner().SetHarmonyScoping(true);
610 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000611}
612
613
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000614FunctionLiteral* Parser::ParseProgram(CompilationInfo* info) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000615 ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
Steve Blocka7e24c12009-10-30 11:49:00 +0000616
Steve Block44f0eee2011-05-26 01:26:41 +0100617 HistogramTimerScope timer(isolate()->counters()->parse());
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000618 Handle<String> source(String::cast(script_->source()));
Steve Block44f0eee2011-05-26 01:26:41 +0100619 isolate()->counters()->total_parse_size()->Increment(source->length());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000620 fni_ = new(zone()) FuncNameInferrer(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000621
622 // Initialize parser state.
Steve Block6ded16b2010-05-10 14:33:55 +0100623 source->TryFlatten();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100624 if (source->IsExternalTwoByteString()) {
625 // Notice that the stream is destroyed at the end of the branch block.
626 // The last line of the blocks can't be moved outside, even though they're
627 // identical calls.
628 ExternalTwoByteStringUC16CharacterStream stream(
629 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100630 scanner_.Initialize(&stream);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000631 return DoParseProgram(info, source, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100632 } else {
633 GenericStringUC16CharacterStream stream(source, 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100634 scanner_.Initialize(&stream);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000635 return DoParseProgram(info, source, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100636 }
637}
638
639
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000640FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
641 Handle<String> source,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100642 ZoneScope* zone_scope) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000643 ASSERT(top_scope_ == NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000644 ASSERT(target_stack_ == NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100645 if (pre_data_ != NULL) pre_data_->Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000646
647 // Compute the parsing mode.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000648 mode_ = (FLAG_lazy && allow_lazy_) ? PARSE_LAZILY : PARSE_EAGERLY;
Steve Blocka7e24c12009-10-30 11:49:00 +0000649 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
650
Steve Block44f0eee2011-05-26 01:26:41 +0100651 Handle<String> no_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000652
653 FunctionLiteral* result = NULL;
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000654 { Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
655 info->SetGlobalScope(scope);
656 if (!info->is_global()) {
657 scope = Scope::DeserializeScopeChain(*info->calling_context(), scope);
658 scope = NewScope(scope, EVAL_SCOPE);
Steve Block1e0659c2011-05-24 12:43:12 +0100659 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000660 scope->set_start_position(0);
661 scope->set_end_position(source->length());
662 FunctionState function_state(this, scope, isolate());
663 top_scope_->SetLanguageMode(info->language_mode());
Ben Murdoch257744e2011-11-30 15:57:28 +0000664 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16);
Steve Blocka7e24c12009-10-30 11:49:00 +0000665 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100666 int beg_loc = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800667 ParseSourceElements(body, Token::EOS, &ok);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000668 if (ok && !top_scope_->is_classic_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +0100669 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
670 }
Ben Murdoch589d6972011-11-30 16:04:58 +0000671
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000672 if (ok && is_extended_mode()) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000673 CheckConflictingVarDeclarations(scope, &ok);
674 }
675
Steve Blocka7e24c12009-10-30 11:49:00 +0000676 if (ok) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100677 result = new(zone()) FunctionLiteral(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000678 isolate(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000679 no_name,
680 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800681 body,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000682 function_state.materialized_literal_count(),
683 function_state.expected_property_count(),
684 function_state.handler_count(),
685 function_state.only_simple_this_property_assignments(),
686 function_state.this_property_assignments(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000687 0,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000688 FunctionLiteral::ANONYMOUS_EXPRESSION,
689 false); // Does not have duplicate parameters.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100690 } else if (stack_overflow_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100691 isolate()->StackOverflow();
Steve Blocka7e24c12009-10-30 11:49:00 +0000692 }
693 }
694
695 // Make sure the target stack is empty.
696 ASSERT(target_stack_ == NULL);
697
698 // If there was a syntax error we have to get rid of the AST
699 // and it is not safe to do so before the scope has been deleted.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100700 if (result == NULL) zone_scope->DeleteOnExit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000701 return result;
702}
703
Steve Block44f0eee2011-05-26 01:26:41 +0100704FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000705 ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
Steve Block44f0eee2011-05-26 01:26:41 +0100706 HistogramTimerScope timer(isolate()->counters()->parse_lazy());
Ben Murdochf87a2032010-10-22 12:50:53 +0100707 Handle<String> source(String::cast(script_->source()));
Steve Block44f0eee2011-05-26 01:26:41 +0100708 isolate()->counters()->total_parse_size()->Increment(source->length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000709
Steve Block44f0eee2011-05-26 01:26:41 +0100710 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100711 // Initialize parser state.
712 source->TryFlatten();
713 if (source->IsExternalTwoByteString()) {
714 ExternalTwoByteStringUC16CharacterStream stream(
715 Handle<ExternalTwoByteString>::cast(source),
Steve Block44f0eee2011-05-26 01:26:41 +0100716 shared_info->start_position(),
717 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100718 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
719 return result;
720 } else {
721 GenericStringUC16CharacterStream stream(source,
Steve Block44f0eee2011-05-26 01:26:41 +0100722 shared_info->start_position(),
723 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100724 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
725 return result;
726 }
727}
728
729
Steve Block44f0eee2011-05-26 01:26:41 +0100730FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100731 UC16CharacterStream* source,
732 ZoneScope* zone_scope) {
Steve Block44f0eee2011-05-26 01:26:41 +0100733 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Steve Block9fac8402011-05-12 15:51:54 +0100734 scanner_.Initialize(source);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000735 ASSERT(top_scope_ == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100736 ASSERT(target_stack_ == NULL);
737
Steve Block44f0eee2011-05-26 01:26:41 +0100738 Handle<String> name(String::cast(shared_info->name()));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000739 fni_ = new(zone()) FuncNameInferrer(isolate());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100740 fni_->PushEnclosingName(name);
741
Steve Blocka7e24c12009-10-30 11:49:00 +0000742 mode_ = PARSE_EAGERLY;
743
744 // Place holder for the result.
745 FunctionLiteral* result = NULL;
746
747 {
748 // Parse the function literal.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000749 Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
750 info->SetGlobalScope(scope);
Steve Block44f0eee2011-05-26 01:26:41 +0100751 if (!info->closure().is_null()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000752 scope = Scope::DeserializeScopeChain(info->closure()->context(), scope);
Steve Block44f0eee2011-05-26 01:26:41 +0100753 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000754 FunctionState function_state(this, scope, isolate());
755 ASSERT(scope->language_mode() != STRICT_MODE || !info->is_classic_mode());
756 ASSERT(scope->language_mode() != EXTENDED_MODE ||
757 info->is_extended_mode());
758 ASSERT(info->language_mode() == shared_info->language_mode());
759 scope->SetLanguageMode(shared_info->language_mode());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000760 FunctionLiteral::Type type = shared_info->is_expression()
761 ? (shared_info->is_anonymous()
762 ? FunctionLiteral::ANONYMOUS_EXPRESSION
763 : FunctionLiteral::NAMED_EXPRESSION)
764 : FunctionLiteral::DECLARATION;
Steve Blocka7e24c12009-10-30 11:49:00 +0000765 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100766 result = ParseFunctionLiteral(name,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000767 false, // Strict mode name already checked.
768 RelocInfo::kNoPosition,
769 type,
770 &ok);
Steve Blocka7e24c12009-10-30 11:49:00 +0000771 // Make sure the results agree.
772 ASSERT(ok == (result != NULL));
Steve Blocka7e24c12009-10-30 11:49:00 +0000773 }
774
775 // Make sure the target stack is empty.
776 ASSERT(target_stack_ == NULL);
777
778 // If there was a stack overflow we have to get rid of AST and it is
779 // not safe to do before scope has been deleted.
780 if (result == NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100781 zone_scope->DeleteOnExit();
Steve Block44f0eee2011-05-26 01:26:41 +0100782 if (stack_overflow_) isolate()->StackOverflow();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100783 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100784 Handle<String> inferred_name(shared_info->inferred_name());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100785 result->set_inferred_name(inferred_name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000786 }
787 return result;
788}
789
Ben Murdochf87a2032010-10-22 12:50:53 +0100790
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800791Handle<String> Parser::GetSymbol(bool* ok) {
792 int symbol_id = -1;
793 if (pre_data() != NULL) {
794 symbol_id = pre_data()->GetSymbolIdentifier();
Leon Clarke4515c472010-02-03 11:58:03 +0000795 }
Steve Block9fac8402011-05-12 15:51:54 +0100796 return LookupSymbol(symbol_id);
Leon Clarke4515c472010-02-03 11:58:03 +0000797}
Steve Blocka7e24c12009-10-30 11:49:00 +0000798
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800799
Steve Blocka7e24c12009-10-30 11:49:00 +0000800void Parser::ReportMessage(const char* type, Vector<const char*> args) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100801 Scanner::Location source_location = scanner().location();
Steve Blocka7e24c12009-10-30 11:49:00 +0000802 ReportMessageAt(source_location, type, args);
803}
804
805
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800806void Parser::ReportMessageAt(Scanner::Location source_location,
807 const char* type,
808 Vector<const char*> args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000809 MessageLocation location(script_,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100810 source_location.beg_pos,
811 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100812 Factory* factory = isolate()->factory();
813 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000814 for (int i = 0; i < args.length(); i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100815 Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100816 elements->set(i, *arg_string);
Steve Blocka7e24c12009-10-30 11:49:00 +0000817 }
Steve Block44f0eee2011-05-26 01:26:41 +0100818 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
819 Handle<Object> result = factory->NewSyntaxError(type, array);
820 isolate()->Throw(*result, &location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000821}
822
823
Ben Murdochb8e0da22011-05-16 14:20:40 +0100824void Parser::ReportMessageAt(Scanner::Location source_location,
825 const char* type,
826 Vector<Handle<String> > args) {
827 MessageLocation location(script_,
828 source_location.beg_pos,
829 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100830 Factory* factory = isolate()->factory();
831 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100832 for (int i = 0; i < args.length(); i++) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100833 elements->set(i, *args[i]);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100834 }
Steve Block44f0eee2011-05-26 01:26:41 +0100835 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
836 Handle<Object> result = factory->NewSyntaxError(type, array);
837 isolate()->Throw(*result, &location);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100838}
839
840
Steve Blocka7e24c12009-10-30 11:49:00 +0000841// Base class containing common code for the different finder classes used by
842// the parser.
843class ParserFinder {
844 protected:
845 ParserFinder() {}
846 static Assignment* AsAssignment(Statement* stat) {
847 if (stat == NULL) return NULL;
848 ExpressionStatement* exp_stat = stat->AsExpressionStatement();
849 if (exp_stat == NULL) return NULL;
850 return exp_stat->expression()->AsAssignment();
851 }
852};
853
854
855// An InitializationBlockFinder finds and marks sequences of statements of the
Steve Blockd0582a62009-12-15 09:54:21 +0000856// form expr.a = ...; expr.b = ...; etc.
Steve Blocka7e24c12009-10-30 11:49:00 +0000857class InitializationBlockFinder : public ParserFinder {
858 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000859 // We find and mark the initialization blocks in top level
860 // non-looping code only. This is because the optimization prevents
861 // reuse of the map transitions, so it should be used only for code
862 // that will only be run once.
863 InitializationBlockFinder(Scope* top_scope, Target* target)
864 : enabled_(top_scope->DeclarationScope()->is_global_scope() &&
865 !IsLoopTarget(target)),
866 first_in_block_(NULL),
867 last_in_block_(NULL),
868 block_size_(0) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000869
870 ~InitializationBlockFinder() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000871 if (!enabled_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000872 if (InBlock()) EndBlock();
873 }
874
875 void Update(Statement* stat) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000876 if (!enabled_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000877 Assignment* assignment = AsAssignment(stat);
878 if (InBlock()) {
879 if (BlockContinues(assignment)) {
880 UpdateBlock(assignment);
881 } else {
882 EndBlock();
883 }
884 }
885 if (!InBlock() && (assignment != NULL) &&
886 (assignment->op() == Token::ASSIGN)) {
887 StartBlock(assignment);
888 }
889 }
890
891 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800892 // The minimum number of contiguous assignment that will
893 // be treated as an initialization block. Benchmarks show that
894 // the overhead exceeds the savings below this limit.
895 static const int kMinInitializationBlock = 3;
896
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000897 static bool IsLoopTarget(Target* target) {
898 while (target != NULL) {
899 if (target->node()->AsIterationStatement() != NULL) return true;
900 target = target->previous();
901 }
902 return false;
903 }
904
Steve Blocka7e24c12009-10-30 11:49:00 +0000905 // Returns true if the expressions appear to denote the same object.
906 // In the context of initialization blocks, we only consider expressions
Steve Blockd0582a62009-12-15 09:54:21 +0000907 // of the form 'expr.x' or expr["x"].
Steve Blocka7e24c12009-10-30 11:49:00 +0000908 static bool SameObject(Expression* e1, Expression* e2) {
909 VariableProxy* v1 = e1->AsVariableProxy();
910 VariableProxy* v2 = e2->AsVariableProxy();
911 if (v1 != NULL && v2 != NULL) {
912 return v1->name()->Equals(*v2->name());
913 }
914 Property* p1 = e1->AsProperty();
915 Property* p2 = e2->AsProperty();
916 if ((p1 == NULL) || (p2 == NULL)) return false;
917 Literal* key1 = p1->key()->AsLiteral();
918 Literal* key2 = p2->key()->AsLiteral();
919 if ((key1 == NULL) || (key2 == NULL)) return false;
920 if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
921 return false;
922 }
923 String* name1 = String::cast(*key1->handle());
924 String* name2 = String::cast(*key2->handle());
925 if (!name1->Equals(name2)) return false;
926 return SameObject(p1->obj(), p2->obj());
927 }
928
929 // Returns true if the expressions appear to denote different properties
930 // of the same object.
931 static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
932 Property* p1 = e1->AsProperty();
933 Property* p2 = e2->AsProperty();
934 if ((p1 == NULL) || (p2 == NULL)) return false;
935 return SameObject(p1->obj(), p2->obj());
936 }
937
938 bool BlockContinues(Assignment* assignment) {
939 if ((assignment == NULL) || (first_in_block_ == NULL)) return false;
940 if (assignment->op() != Token::ASSIGN) return false;
941 return PropertyOfSameObject(first_in_block_->target(),
942 assignment->target());
943 }
944
945 void StartBlock(Assignment* assignment) {
946 first_in_block_ = assignment;
947 last_in_block_ = assignment;
948 block_size_ = 1;
949 }
950
951 void UpdateBlock(Assignment* assignment) {
952 last_in_block_ = assignment;
953 ++block_size_;
954 }
955
956 void EndBlock() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800957 if (block_size_ >= kMinInitializationBlock) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000958 first_in_block_->mark_block_start();
959 last_in_block_->mark_block_end();
960 }
961 last_in_block_ = first_in_block_ = NULL;
962 block_size_ = 0;
963 }
964
965 bool InBlock() { return first_in_block_ != NULL; }
966
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000967 const bool enabled_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000968 Assignment* first_in_block_;
969 Assignment* last_in_block_;
970 int block_size_;
971
972 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
973};
974
975
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000976// A ThisNamedPropertyAssignmentFinder finds and marks statements of the form
Steve Blocka7e24c12009-10-30 11:49:00 +0000977// this.x = ...;, where x is a named property. It also determines whether a
978// function contains only assignments of this type.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000979class ThisNamedPropertyAssignmentFinder : public ParserFinder {
Steve Blocka7e24c12009-10-30 11:49:00 +0000980 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000981 explicit ThisNamedPropertyAssignmentFinder(Isolate* isolate)
Steve Block44f0eee2011-05-26 01:26:41 +0100982 : isolate_(isolate),
983 only_simple_this_property_assignments_(true),
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000984 names_(0),
985 assigned_arguments_(0),
986 assigned_constants_(0) {
987 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000988
989 void Update(Scope* scope, Statement* stat) {
Steve Blockd0582a62009-12-15 09:54:21 +0000990 // Bail out if function already has property assignment that are
991 // not simple this property assignments.
992 if (!only_simple_this_property_assignments_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000993 return;
994 }
995
996 // Check whether this statement is of the form this.x = ...;
997 Assignment* assignment = AsAssignment(stat);
998 if (IsThisPropertyAssignment(assignment)) {
999 HandleThisPropertyAssignment(scope, assignment);
1000 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00001001 only_simple_this_property_assignments_ = false;
1002 }
1003 }
1004
Steve Blocka7e24c12009-10-30 11:49:00 +00001005 // Returns whether only statements of the form this.x = y; where y is either a
1006 // constant or a function argument was encountered.
1007 bool only_simple_this_property_assignments() {
1008 return only_simple_this_property_assignments_;
1009 }
1010
1011 // Returns a fixed array containing three elements for each assignment of the
1012 // form this.x = y;
1013 Handle<FixedArray> GetThisPropertyAssignments() {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001014 if (names_.is_empty()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001015 return isolate_->factory()->empty_fixed_array();
Steve Blocka7e24c12009-10-30 11:49:00 +00001016 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001017 ASSERT_EQ(names_.length(), assigned_arguments_.length());
1018 ASSERT_EQ(names_.length(), assigned_constants_.length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001019 Handle<FixedArray> assignments =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001020 isolate_->factory()->NewFixedArray(names_.length() * 3);
1021 for (int i = 0; i < names_.length(); ++i) {
1022 assignments->set(i * 3, *names_[i]);
1023 assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_[i]));
1024 assignments->set(i * 3 + 2, *assigned_constants_[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001025 }
1026 return assignments;
1027 }
1028
1029 private:
1030 bool IsThisPropertyAssignment(Assignment* assignment) {
1031 if (assignment != NULL) {
1032 Property* property = assignment->target()->AsProperty();
1033 return assignment->op() == Token::ASSIGN
1034 && property != NULL
1035 && property->obj()->AsVariableProxy() != NULL
1036 && property->obj()->AsVariableProxy()->is_this();
1037 }
1038 return false;
1039 }
1040
1041 void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
Steve Block6ded16b2010-05-10 14:33:55 +01001042 // Check that the property assigned to is a named property, which is not
1043 // __proto__.
Steve Blocka7e24c12009-10-30 11:49:00 +00001044 Property* property = assignment->target()->AsProperty();
1045 ASSERT(property != NULL);
1046 Literal* literal = property->key()->AsLiteral();
1047 uint32_t dummy;
1048 if (literal != NULL &&
1049 literal->handle()->IsString() &&
Steve Block44f0eee2011-05-26 01:26:41 +01001050 !String::cast(*(literal->handle()))->Equals(
1051 isolate_->heap()->Proto_symbol()) &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001052 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
1053 Handle<String> key = Handle<String>::cast(literal->handle());
1054
1055 // Check whether the value assigned is either a constant or matches the
1056 // name of one of the arguments to the function.
1057 if (assignment->value()->AsLiteral() != NULL) {
1058 // Constant assigned.
1059 Literal* literal = assignment->value()->AsLiteral();
1060 AssignmentFromConstant(key, literal->handle());
Steve Blockd0582a62009-12-15 09:54:21 +00001061 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001062 } else if (assignment->value()->AsVariableProxy() != NULL) {
1063 // Variable assigned.
1064 Handle<String> name =
1065 assignment->value()->AsVariableProxy()->name();
1066 // Check whether the variable assigned matches an argument name.
Steve Blocka7e24c12009-10-30 11:49:00 +00001067 for (int i = 0; i < scope->num_parameters(); i++) {
1068 if (*scope->parameter(i)->name() == *name) {
1069 // Assigned from function argument.
Steve Blockd0582a62009-12-15 09:54:21 +00001070 AssignmentFromParameter(key, i);
1071 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001072 }
1073 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001074 }
1075 }
Steve Blockd0582a62009-12-15 09:54:21 +00001076 // It is not a simple "this.x = value;" assignment with a constant
1077 // or parameter value.
1078 AssignmentFromSomethingElse();
Steve Blocka7e24c12009-10-30 11:49:00 +00001079 }
1080
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001081
1082
1083
1084 // We will potentially reorder the property assignments, so they must be
1085 // simple enough that the ordering does not matter.
Steve Blocka7e24c12009-10-30 11:49:00 +00001086 void AssignmentFromParameter(Handle<String> name, int index) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001087 EnsureInitialized();
1088 for (int i = 0; i < names_.length(); ++i) {
1089 if (name->Equals(*names_[i])) {
1090 assigned_arguments_[i] = index;
1091 assigned_constants_[i] = isolate_->factory()->undefined_value();
1092 return;
1093 }
1094 }
1095 names_.Add(name);
1096 assigned_arguments_.Add(index);
1097 assigned_constants_.Add(isolate_->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001098 }
1099
1100 void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001101 EnsureInitialized();
1102 for (int i = 0; i < names_.length(); ++i) {
1103 if (name->Equals(*names_[i])) {
1104 assigned_arguments_[i] = -1;
1105 assigned_constants_[i] = value;
1106 return;
1107 }
1108 }
1109 names_.Add(name);
1110 assigned_arguments_.Add(-1);
1111 assigned_constants_.Add(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001112 }
1113
Steve Blockd0582a62009-12-15 09:54:21 +00001114 void AssignmentFromSomethingElse() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001115 // The this assignment is not a simple one.
1116 only_simple_this_property_assignments_ = false;
1117 }
1118
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001119 void EnsureInitialized() {
1120 if (names_.capacity() == 0) {
1121 ASSERT(assigned_arguments_.capacity() == 0);
1122 ASSERT(assigned_constants_.capacity() == 0);
1123 names_.Initialize(4);
1124 assigned_arguments_.Initialize(4);
1125 assigned_constants_.Initialize(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001126 }
1127 }
1128
Steve Block44f0eee2011-05-26 01:26:41 +01001129 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001130 bool only_simple_this_property_assignments_;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001131 ZoneStringList names_;
1132 ZoneList<int> assigned_arguments_;
1133 ZoneObjectList assigned_constants_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001134};
1135
1136
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001137Statement* Parser::ParseSourceElement(ZoneStringList* labels,
1138 bool* ok) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001139 // (Ecma 262 5th Edition, clause 14):
1140 // SourceElement:
1141 // Statement
1142 // FunctionDeclaration
1143 //
1144 // In harmony mode we allow additionally the following productions
1145 // SourceElement:
1146 // LetDeclaration
1147 // ConstDeclaration
1148
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001149 if (peek() == Token::FUNCTION) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001150 return ParseFunctionDeclaration(ok);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001151 } else if (peek() == Token::LET || peek() == Token::CONST) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001152 return ParseVariableStatement(kSourceElement, ok);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001153 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001154 return ParseStatement(labels, ok);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001155}
1156
1157
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001158void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
Steve Blocka7e24c12009-10-30 11:49:00 +00001159 int end_token,
1160 bool* ok) {
1161 // SourceElements ::
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001162 // (SourceElement)* <end_token>
Steve Blocka7e24c12009-10-30 11:49:00 +00001163
1164 // Allocate a target stack to use for this set of source
1165 // elements. This way, all scripts and functions get their own
1166 // target stack thus avoiding illegal breaks and continues across
1167 // functions.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001168 TargetScope scope(&this->target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001169
1170 ASSERT(processor != NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001171 InitializationBlockFinder block_finder(top_scope_, target_stack_);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001172 ThisNamedPropertyAssignmentFinder this_property_assignment_finder(isolate());
Steve Block1e0659c2011-05-24 12:43:12 +01001173 bool directive_prologue = true; // Parsing directive prologue.
1174
Steve Blocka7e24c12009-10-30 11:49:00 +00001175 while (peek() != end_token) {
Steve Block1e0659c2011-05-24 12:43:12 +01001176 if (directive_prologue && peek() != Token::STRING) {
1177 directive_prologue = false;
1178 }
1179
1180 Scanner::Location token_loc = scanner().peek_location();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001181 Statement* stat = ParseSourceElement(NULL, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01001182 if (stat == NULL || stat->IsEmpty()) {
1183 directive_prologue = false; // End of directive prologue.
1184 continue;
1185 }
1186
1187 if (directive_prologue) {
1188 // A shot at a directive.
1189 ExpressionStatement *e_stat;
1190 Literal *literal;
1191 // Still processing directive prologue?
1192 if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1193 (literal = e_stat->expression()->AsLiteral()) != NULL &&
1194 literal->handle()->IsString()) {
1195 Handle<String> directive = Handle<String>::cast(literal->handle());
1196
1197 // Check "use strict" directive (ES5 14.1).
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001198 if (top_scope_->is_classic_mode() &&
Steve Block44f0eee2011-05-26 01:26:41 +01001199 directive->Equals(isolate()->heap()->use_strict()) &&
Steve Block1e0659c2011-05-24 12:43:12 +01001200 token_loc.end_pos - token_loc.beg_pos ==
Steve Block44f0eee2011-05-26 01:26:41 +01001201 isolate()->heap()->use_strict()->length() + 2) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001202 // TODO(ES6): Fix entering extended mode, once it is specified.
1203 top_scope_->SetLanguageMode(FLAG_harmony_scoping
1204 ? EXTENDED_MODE : STRICT_MODE);
Steve Block1e0659c2011-05-24 12:43:12 +01001205 // "use strict" is the only directive for now.
1206 directive_prologue = false;
1207 }
1208 } else {
1209 // End of the directive prologue.
1210 directive_prologue = false;
1211 }
1212 }
1213
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001214 block_finder.Update(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00001215 // Find and mark all assignments to named properties in this (this.x =)
1216 if (top_scope_->is_function_scope()) {
1217 this_property_assignment_finder.Update(top_scope_, stat);
1218 }
1219 processor->Add(stat);
1220 }
1221
1222 // Propagate the collected information on this property assignments.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001223 if (top_scope_->is_function_scope()) {
Steve Blockd0582a62009-12-15 09:54:21 +00001224 bool only_simple_this_property_assignments =
Andrei Popescu402d9372010-02-26 13:31:12 +00001225 this_property_assignment_finder.only_simple_this_property_assignments()
1226 && top_scope_->declarations()->length() == 0;
Steve Blockd0582a62009-12-15 09:54:21 +00001227 if (only_simple_this_property_assignments) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001228 current_function_state_->SetThisPropertyAssignmentInfo(
Steve Blockd0582a62009-12-15 09:54:21 +00001229 only_simple_this_property_assignments,
Steve Blocka7e24c12009-10-30 11:49:00 +00001230 this_property_assignment_finder.GetThisPropertyAssignments());
1231 }
1232 }
1233 return 0;
1234}
1235
1236
1237Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1238 // Statement ::
1239 // Block
1240 // VariableStatement
1241 // EmptyStatement
1242 // ExpressionStatement
1243 // IfStatement
1244 // IterationStatement
1245 // ContinueStatement
1246 // BreakStatement
1247 // ReturnStatement
1248 // WithStatement
1249 // LabelledStatement
1250 // SwitchStatement
1251 // ThrowStatement
1252 // TryStatement
1253 // DebuggerStatement
1254
1255 // Note: Since labels can only be used by 'break' and 'continue'
1256 // statements, which themselves are only valid within blocks,
1257 // iterations or 'switch' statements (i.e., BreakableStatements),
1258 // labels can be simply ignored in all other cases; except for
1259 // trivial labeled break statements 'label: break label' which is
1260 // parsed into an empty statement.
1261
1262 // Keep the source position of the statement
1263 int statement_pos = scanner().peek_location().beg_pos;
1264 Statement* stmt = NULL;
1265 switch (peek()) {
1266 case Token::LBRACE:
1267 return ParseBlock(labels, ok);
1268
1269 case Token::CONST: // fall through
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001270 case Token::LET:
Steve Blocka7e24c12009-10-30 11:49:00 +00001271 case Token::VAR:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001272 stmt = ParseVariableStatement(kStatement, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001273 break;
1274
1275 case Token::SEMICOLON:
1276 Next();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001277 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001278
1279 case Token::IF:
1280 stmt = ParseIfStatement(labels, ok);
1281 break;
1282
1283 case Token::DO:
Steve Block3ce2e202009-11-05 08:53:23 +00001284 stmt = ParseDoWhileStatement(labels, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001285 break;
1286
1287 case Token::WHILE:
1288 stmt = ParseWhileStatement(labels, ok);
1289 break;
1290
1291 case Token::FOR:
1292 stmt = ParseForStatement(labels, ok);
1293 break;
1294
1295 case Token::CONTINUE:
1296 stmt = ParseContinueStatement(ok);
1297 break;
1298
1299 case Token::BREAK:
1300 stmt = ParseBreakStatement(labels, ok);
1301 break;
1302
1303 case Token::RETURN:
1304 stmt = ParseReturnStatement(ok);
1305 break;
1306
1307 case Token::WITH:
1308 stmt = ParseWithStatement(labels, ok);
1309 break;
1310
1311 case Token::SWITCH:
1312 stmt = ParseSwitchStatement(labels, ok);
1313 break;
1314
1315 case Token::THROW:
1316 stmt = ParseThrowStatement(ok);
1317 break;
1318
1319 case Token::TRY: {
1320 // NOTE: It is somewhat complicated to have labels on
1321 // try-statements. When breaking out of a try-finally statement,
1322 // one must take great care not to treat it as a
1323 // fall-through. It is much easier just to wrap the entire
1324 // try-statement in a statement block and put the labels there
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001325 Block* result = new(zone()) Block(isolate(), labels, 1, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001326 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001327 TryStatement* statement = ParseTryStatement(CHECK_OK);
1328 if (statement) {
1329 statement->set_statement_pos(statement_pos);
1330 }
1331 if (result) result->AddStatement(statement);
1332 return result;
1333 }
1334
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001335 case Token::FUNCTION: {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001336 // FunctionDeclaration is only allowed in the context of SourceElements
1337 // (Ecma 262 5th Edition, clause 14):
1338 // SourceElement:
1339 // Statement
1340 // FunctionDeclaration
1341 // Common language extension is to allow function declaration in place
1342 // of any statement. This language extension is disabled in strict mode.
1343 if (!top_scope_->is_classic_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001344 ReportMessageAt(scanner().peek_location(), "strict_function",
1345 Vector<const char*>::empty());
1346 *ok = false;
1347 return NULL;
1348 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001349 return ParseFunctionDeclaration(ok);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001350 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001351
Steve Blocka7e24c12009-10-30 11:49:00 +00001352 case Token::DEBUGGER:
1353 stmt = ParseDebuggerStatement(ok);
1354 break;
1355
1356 default:
1357 stmt = ParseExpressionOrLabelledStatement(labels, ok);
1358 }
1359
1360 // Store the source position of the statement
1361 if (stmt != NULL) stmt->set_statement_pos(statement_pos);
1362 return stmt;
1363}
1364
1365
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001366VariableProxy* Parser::Declare(Handle<String> name,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001367 VariableMode mode,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001368 FunctionLiteral* fun,
1369 bool resolve,
1370 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001371 Variable* var = NULL;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001372 // If we are inside a function, a declaration of a var/const variable is a
1373 // truly local variable, and the scope of the variable is always the function
1374 // scope.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001375 // Let/const variables in harmony mode are always added to the immediately
1376 // enclosing scope.
1377 Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY)
1378 ? top_scope_ : top_scope_->DeclarationScope();
1379 InitializationFlag init_flag = (fun != NULL || mode == VAR)
1380 ? kCreatedInitialized : kNeedsInitialization;
Steve Blocka7e24c12009-10-30 11:49:00 +00001381
1382 // If a function scope exists, then we can statically declare this
1383 // variable and also set its mode. In any case, a Declaration node
1384 // will be added to the scope so that the declaration can be added
1385 // to the corresponding activation frame at runtime if necessary.
1386 // For instance declarations inside an eval scope need to be added
1387 // to the calling function context.
Ben Murdoch257744e2011-11-30 15:57:28 +00001388 // Similarly, strict mode eval scope does not leak variable declarations to
1389 // the caller's scope so we declare all locals, too.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001390 // Also for block scoped let/const bindings the variable can be
1391 // statically declared.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001392 if (declaration_scope->is_function_scope() ||
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001393 declaration_scope->is_strict_or_extended_eval_scope() ||
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001394 declaration_scope->is_block_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001395 // Declare the variable in the function scope.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001396 var = declaration_scope->LocalLookup(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001397 if (var == NULL) {
1398 // Declare the name.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001399 var = declaration_scope->DeclareLocal(name, mode, init_flag);
Steve Blocka7e24c12009-10-30 11:49:00 +00001400 } else {
Ben Murdoch589d6972011-11-30 16:04:58 +00001401 // The name was declared in this scope before; check for conflicting
1402 // re-declarations. We have a conflict if either of the declarations is
1403 // not a var. There is similar code in runtime.cc in the Declare
1404 // functions. The function CheckNonConflictingScope checks for conflicting
1405 // var and let bindings from different scopes whereas this is a check for
1406 // conflicting declarations within the same scope. This check also covers
1407 //
1408 // function () { let x; { var x; } }
1409 //
1410 // because the var declaration is hoisted to the function scope where 'x'
1411 // is already bound.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001412 if ((mode != VAR) || (var->mode() != VAR)) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001413 // We only have vars, consts and lets in declarations.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001414 ASSERT(var->mode() == VAR ||
1415 var->mode() == CONST ||
1416 var->mode() == CONST_HARMONY ||
1417 var->mode() == LET);
1418 if (is_extended_mode()) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001419 // In harmony mode we treat re-declarations as early errors. See
1420 // ES5 16 for a definition of early errors.
1421 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
1422 const char* elms[2] = { "Variable", *c_string };
1423 Vector<const char*> args(elms, 2);
1424 ReportMessage("redeclaration", args);
1425 *ok = false;
1426 return NULL;
1427 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001428 const char* type = (var->mode() == VAR)
1429 ? "var" : var->is_const_mode() ? "const" : "let";
Steve Blocka7e24c12009-10-30 11:49:00 +00001430 Handle<String> type_string =
Steve Block44f0eee2011-05-26 01:26:41 +01001431 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00001432 Expression* expression =
Steve Block44f0eee2011-05-26 01:26:41 +01001433 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00001434 type_string, name);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001435 declaration_scope->SetIllegalRedeclaration(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00001436 }
1437 }
1438 }
1439
1440 // We add a declaration node for every declaration. The compiler
1441 // will only generate code if necessary. In particular, declarations
1442 // for inner local variables that do not represent functions won't
1443 // result in any generated code.
1444 //
1445 // Note that we always add an unresolved proxy even if it's not
1446 // used, simply because we don't know in this method (w/o extra
1447 // parameters) if the proxy is needed or not. The proxy will be
1448 // bound during variable resolution time unless it was pre-bound
1449 // below.
1450 //
1451 // WARNING: This will lead to multiple declaration nodes for the
1452 // same variable if it is declared several times. This is not a
1453 // semantic issue as long as we keep the source order, but it may be
1454 // a performance issue since it may lead to repeated
1455 // Runtime::DeclareContextSlot() calls.
Ben Murdoch589d6972011-11-30 16:04:58 +00001456 VariableProxy* proxy = declaration_scope->NewUnresolved(
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001457 name, scanner().location().beg_pos);
Ben Murdoch589d6972011-11-30 16:04:58 +00001458 declaration_scope->AddDeclaration(
1459 new(zone()) Declaration(proxy, mode, fun, top_scope_));
Steve Blocka7e24c12009-10-30 11:49:00 +00001460
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001461 if ((mode == CONST || mode == CONST_HARMONY) &&
1462 declaration_scope->is_global_scope()) {
1463 // For global const variables we bind the proxy to a variable.
Steve Blocka7e24c12009-10-30 11:49:00 +00001464 ASSERT(resolve); // should be set by all callers
1465 Variable::Kind kind = Variable::NORMAL;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001466 var = new(zone()) Variable(declaration_scope,
1467 name,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001468 mode,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001469 true,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001470 kind,
1471 kNeedsInitialization);
1472 } else if (declaration_scope->is_eval_scope() &&
1473 declaration_scope->is_classic_mode()) {
1474 // For variable declarations in a non-strict eval scope the proxy is bound
1475 // to a lookup variable to force a dynamic declaration using the
1476 // DeclareContextSlot runtime function.
1477 Variable::Kind kind = Variable::NORMAL;
1478 var = new(zone()) Variable(declaration_scope,
1479 name,
1480 mode,
1481 true,
1482 kind,
1483 init_flag);
1484 var->AllocateTo(Variable::LOOKUP, -1);
1485 resolve = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001486 }
1487
1488 // If requested and we have a local variable, bind the proxy to the variable
1489 // at parse-time. This is used for functions (and consts) declared inside
1490 // statements: the corresponding function (or const) variable must be in the
1491 // function scope and not a statement-local scope, e.g. as provided with a
1492 // 'with' statement:
1493 //
1494 // with (obj) {
1495 // function f() {}
1496 // }
1497 //
1498 // which is translated into:
1499 //
1500 // with (obj) {
1501 // // in this case this is not: 'var f; f = function () {};'
1502 // var f = function () {};
1503 // }
1504 //
1505 // Note that if 'f' is accessed from inside the 'with' statement, it
1506 // will be allocated in the context (because we must be able to look
1507 // it up dynamically) but it will also be accessed statically, i.e.,
1508 // with a context slot index and a context chain length for this
1509 // initialization code. Thus, inside the 'with' statement, we need
1510 // both access to the static and the dynamic context chain; the
1511 // runtime needs to provide both.
1512 if (resolve && var != NULL) proxy->BindTo(var);
1513
1514 return proxy;
1515}
1516
1517
1518// Language extension which is only enabled for source files loaded
1519// through the API's extension mechanism. A native function
1520// declaration is resolved by looking up the function through a
1521// callback provided by the extension.
1522Statement* Parser::ParseNativeDeclaration(bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001523 Expect(Token::FUNCTION, CHECK_OK);
1524 Handle<String> name = ParseIdentifier(CHECK_OK);
1525 Expect(Token::LPAREN, CHECK_OK);
1526 bool done = (peek() == Token::RPAREN);
1527 while (!done) {
1528 ParseIdentifier(CHECK_OK);
1529 done = (peek() == Token::RPAREN);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001530 if (!done) {
1531 Expect(Token::COMMA, CHECK_OK);
1532 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001533 }
1534 Expect(Token::RPAREN, CHECK_OK);
1535 Expect(Token::SEMICOLON, CHECK_OK);
1536
Steve Blocka7e24c12009-10-30 11:49:00 +00001537 // Make sure that the function containing the native declaration
1538 // isn't lazily compiled. The extension structures are only
1539 // accessible while parsing the first time not when reparsing
1540 // because of lazy compilation.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001541 top_scope_->DeclarationScope()->ForceEagerCompilation();
Steve Blocka7e24c12009-10-30 11:49:00 +00001542
1543 // Compute the function template for the native function.
1544 v8::Handle<v8::FunctionTemplate> fun_template =
1545 extension_->GetNativeFunction(v8::Utils::ToLocal(name));
1546 ASSERT(!fun_template.IsEmpty());
1547
Steve Block6ded16b2010-05-10 14:33:55 +01001548 // Instantiate the function and create a shared function info from it.
Steve Blocka7e24c12009-10-30 11:49:00 +00001549 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1550 const int literals = fun->NumberOfLiterals();
1551 Handle<Code> code = Handle<Code>(fun->shared()->code());
Leon Clarkee46be812010-01-19 14:06:41 +00001552 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
Steve Block6ded16b2010-05-10 14:33:55 +01001553 Handle<SharedFunctionInfo> shared =
Steve Block44f0eee2011-05-26 01:26:41 +01001554 isolate()->factory()->NewSharedFunctionInfo(name, literals, code,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001555 Handle<ScopeInfo>(fun->shared()->scope_info()));
Steve Block6ded16b2010-05-10 14:33:55 +01001556 shared->set_construct_stub(*construct_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +00001557
Steve Block6ded16b2010-05-10 14:33:55 +01001558 // Copy the function data to the shared function info.
1559 shared->set_function_data(fun->shared()->function_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00001560 int parameters = fun->shared()->formal_parameter_count();
Steve Block6ded16b2010-05-10 14:33:55 +01001561 shared->set_formal_parameter_count(parameters);
Steve Blocka7e24c12009-10-30 11:49:00 +00001562
1563 // TODO(1240846): It's weird that native function declarations are
1564 // introduced dynamically when we meet their declarations, whereas
1565 // other functions are setup when entering the surrounding scope.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001566 SharedFunctionInfoLiteral* lit =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001567 new(zone()) SharedFunctionInfoLiteral(isolate(), shared);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001568 VariableProxy* var = Declare(name, VAR, NULL, true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001569 return new(zone()) ExpressionStatement(new(zone()) Assignment(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001570 isolate(), Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
Steve Blocka7e24c12009-10-30 11:49:00 +00001571}
1572
1573
1574Statement* Parser::ParseFunctionDeclaration(bool* ok) {
1575 // FunctionDeclaration ::
1576 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1577 Expect(Token::FUNCTION, CHECK_OK);
1578 int function_token_position = scanner().location().beg_pos;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001579 bool is_strict_reserved = false;
1580 Handle<String> name = ParseIdentifierOrStrictReservedWord(
1581 &is_strict_reserved, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001582 FunctionLiteral* fun = ParseFunctionLiteral(name,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001583 is_strict_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00001584 function_token_position,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001585 FunctionLiteral::DECLARATION,
Steve Blocka7e24c12009-10-30 11:49:00 +00001586 CHECK_OK);
1587 // Even if we're not at the top-level of the global or a function
1588 // scope, we treat is as such and introduce the function with it's
1589 // initial value upon entering the corresponding scope.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001590 VariableMode mode = is_extended_mode() ? LET : VAR;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001591 Declare(name, mode, fun, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001592 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001593}
1594
1595
1596Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001597 if (top_scope_->is_extended_mode()) return ParseScopedBlock(labels, ok);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001598
Steve Blocka7e24c12009-10-30 11:49:00 +00001599 // Block ::
1600 // '{' Statement* '}'
1601
1602 // Note that a Block does not introduce a new execution scope!
1603 // (ECMA-262, 3rd, 12.2)
1604 //
1605 // Construct block expecting 16 statements.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001606 Block* result = new(zone()) Block(isolate(), labels, 16, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001607 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001608 Expect(Token::LBRACE, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001609 InitializationBlockFinder block_finder(top_scope_, target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001610 while (peek() != Token::RBRACE) {
1611 Statement* stat = ParseStatement(NULL, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001612 if (stat && !stat->IsEmpty()) {
1613 result->AddStatement(stat);
1614 block_finder.Update(stat);
1615 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001616 }
1617 Expect(Token::RBRACE, CHECK_OK);
1618 return result;
1619}
1620
1621
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001622Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001623 // The harmony mode uses source elements instead of statements.
1624 //
1625 // Block ::
1626 // '{' SourceElement* '}'
1627
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001628 // Construct block expecting 16 statements.
1629 Block* body = new(zone()) Block(isolate(), labels, 16, false);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001630 Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001631
1632 // Parse the statements and collect escaping labels.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001633 Expect(Token::LBRACE, CHECK_OK);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001634 block_scope->set_start_position(scanner().location().beg_pos);
1635 { BlockState block_state(this, block_scope);
1636 TargetCollector collector;
1637 Target target(&this->target_stack_, &collector);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001638 Target target_body(&this->target_stack_, body);
1639 InitializationBlockFinder block_finder(top_scope_, target_stack_);
1640
1641 while (peek() != Token::RBRACE) {
1642 Statement* stat = ParseSourceElement(NULL, CHECK_OK);
1643 if (stat && !stat->IsEmpty()) {
1644 body->AddStatement(stat);
1645 block_finder.Update(stat);
1646 }
1647 }
1648 }
1649 Expect(Token::RBRACE, CHECK_OK);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001650 block_scope->set_end_position(scanner().location().end_pos);
Ben Murdoch589d6972011-11-30 16:04:58 +00001651 block_scope = block_scope->FinalizeBlockScope();
1652 body->set_block_scope(block_scope);
1653 return body;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001654}
1655
1656
1657Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
1658 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001659 // VariableStatement ::
1660 // VariableDeclarations ';'
1661
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001662 Handle<String> ignore;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001663 Block* result = ParseVariableDeclarations(var_context,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001664 NULL,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001665 &ignore,
1666 CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001667 ExpectSemicolon(CHECK_OK);
1668 return result;
1669}
1670
Steve Block44f0eee2011-05-26 01:26:41 +01001671
1672bool Parser::IsEvalOrArguments(Handle<String> string) {
1673 return string.is_identical_to(isolate()->factory()->eval_symbol()) ||
1674 string.is_identical_to(isolate()->factory()->arguments_symbol());
Steve Block1e0659c2011-05-24 12:43:12 +01001675}
Steve Blocka7e24c12009-10-30 11:49:00 +00001676
Steve Block44f0eee2011-05-26 01:26:41 +01001677
Steve Blocka7e24c12009-10-30 11:49:00 +00001678// If the variable declaration declares exactly one non-const
1679// variable, then *var is set to that variable. In all other cases,
1680// *var is untouched; in particular, it is the caller's responsibility
1681// to initialize it properly. This mechanism is used for the parsing
1682// of 'for-in' loops.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001683Block* Parser::ParseVariableDeclarations(
1684 VariableDeclarationContext var_context,
1685 VariableDeclarationProperties* decl_props,
1686 Handle<String>* out,
1687 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001688 // VariableDeclarations ::
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001689 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
1690 //
1691 // The ES6 Draft Rev3 specifies the following grammar for const declarations
1692 //
1693 // ConstDeclaration ::
1694 // const ConstBinding (',' ConstBinding)* ';'
1695 // ConstBinding ::
1696 // Identifier '=' AssignmentExpression
1697 //
1698 // TODO(ES6):
1699 // ConstBinding ::
1700 // BindingPattern '=' AssignmentExpression
1701 VariableMode mode = VAR;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001702 // True if the binding needs initialization. 'let' and 'const' declared
1703 // bindings are created uninitialized by their declaration nodes and
1704 // need initialization. 'var' declared bindings are always initialized
1705 // immediately by their declaration nodes.
1706 bool needs_init = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001707 bool is_const = false;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001708 Token::Value init_op = Token::INIT_VAR;
Steve Blocka7e24c12009-10-30 11:49:00 +00001709 if (peek() == Token::VAR) {
1710 Consume(Token::VAR);
1711 } else if (peek() == Token::CONST) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001712 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
1713 //
1714 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
1715 //
1716 // * It is a Syntax Error if the code that matches this production is not
1717 // contained in extended code.
1718 //
1719 // However disallowing const in classic mode will break compatibility with
1720 // existing pages. Therefore we keep allowing const with the old
1721 // non-harmony semantics in classic mode.
Steve Blocka7e24c12009-10-30 11:49:00 +00001722 Consume(Token::CONST);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001723 switch (top_scope_->language_mode()) {
1724 case CLASSIC_MODE:
1725 mode = CONST;
1726 init_op = Token::INIT_CONST;
1727 break;
1728 case STRICT_MODE:
1729 ReportMessage("strict_const", Vector<const char*>::empty());
1730 *ok = false;
1731 return NULL;
1732 case EXTENDED_MODE:
1733 if (var_context != kSourceElement &&
1734 var_context != kForStatement) {
1735 // In extended mode 'const' declarations are only allowed in source
1736 // element positions.
1737 ReportMessage("unprotected_const", Vector<const char*>::empty());
1738 *ok = false;
1739 return NULL;
1740 }
1741 mode = CONST_HARMONY;
1742 init_op = Token::INIT_CONST_HARMONY;
1743 }
1744 is_const = true;
1745 needs_init = true;
1746 } else if (peek() == Token::LET) {
1747 // ES6 Draft Rev4 section 12.2.1:
1748 //
1749 // LetDeclaration : let LetBindingList ;
1750 //
1751 // * It is a Syntax Error if the code that matches this production is not
1752 // contained in extended code.
1753 if (!is_extended_mode()) {
1754 ReportMessage("illegal_let", Vector<const char*>::empty());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001755 *ok = false;
1756 return NULL;
1757 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001758 Consume(Token::LET);
1759 if (var_context != kSourceElement &&
1760 var_context != kForStatement) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001761 // Let declarations are only allowed in source element positions.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001762 ASSERT(var_context == kStatement);
1763 ReportMessage("unprotected_let", Vector<const char*>::empty());
1764 *ok = false;
1765 return NULL;
1766 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001767 mode = LET;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001768 needs_init = true;
1769 init_op = Token::INIT_LET;
Steve Blocka7e24c12009-10-30 11:49:00 +00001770 } else {
1771 UNREACHABLE(); // by current callers
1772 }
1773
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001774 Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001775 ? top_scope_ : top_scope_->DeclarationScope();
1776 // The scope of a var/const declared variable anywhere inside a function
Steve Blocka7e24c12009-10-30 11:49:00 +00001777 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001778 // transform a source-level var/const declaration into a (Function)
Steve Blocka7e24c12009-10-30 11:49:00 +00001779 // Scope declaration, and rewrite the source-level initialization into an
1780 // assignment statement. We use a block to collect multiple assignments.
1781 //
1782 // We mark the block as initializer block because we don't want the
1783 // rewriter to add a '.result' assignment to such a block (to get compliant
1784 // behavior for code such as print(eval('var x = 7')), and for cosmetic
1785 // reasons when pretty-printing. Also, unless an assignment (initialization)
1786 // is inside an initializer block, it is ignored.
1787 //
1788 // Create new block with one expected declaration.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001789 Block* block = new(zone()) Block(isolate(), NULL, 1, true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001790 int nvars = 0; // the number of variables declared
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001791 Handle<String> name;
Steve Blocka7e24c12009-10-30 11:49:00 +00001792 do {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001793 if (fni_ != NULL) fni_->Enter();
1794
Steve Blocka7e24c12009-10-30 11:49:00 +00001795 // Parse variable name.
1796 if (nvars > 0) Consume(Token::COMMA);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001797 name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001798 if (fni_ != NULL) fni_->PushVariableName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001799
Steve Block1e0659c2011-05-24 12:43:12 +01001800 // Strict mode variables may not be named eval or arguments
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001801 if (!declaration_scope->is_classic_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01001802 ReportMessage("strict_var_name", Vector<const char*>::empty());
1803 *ok = false;
1804 return NULL;
1805 }
1806
Steve Blocka7e24c12009-10-30 11:49:00 +00001807 // Declare variable.
1808 // Note that we *always* must treat the initial value via a separate init
1809 // assignment for variables and constants because the value must be assigned
1810 // when the variable is encountered in the source. But the variable/constant
1811 // is declared (and set to 'undefined') upon entering the function within
1812 // which the variable or constant is declared. Only function variables have
1813 // an initial value in the declaration (because they are initialized upon
1814 // entering the function).
1815 //
1816 // If we have a const declaration, in an inner scope, the proxy is always
1817 // bound to the declared variable (independent of possibly surrounding with
1818 // statements).
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001819 // For let/const declarations in harmony mode, we can also immediately
1820 // pre-resolve the proxy because it resides in the same scope as the
1821 // declaration.
1822 VariableProxy* proxy = Declare(name, mode, NULL, mode != VAR, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001823 nvars++;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001824 if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
Steve Block053d10c2011-06-13 19:13:29 +01001825 ReportMessageAt(scanner().location(), "too_many_variables",
1826 Vector<const char*>::empty());
1827 *ok = false;
1828 return NULL;
1829 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001830
1831 // Parse initialization expression if present and/or needed. A
1832 // declaration of the form:
1833 //
1834 // var v = x;
1835 //
1836 // is syntactic sugar for:
1837 //
1838 // var v; v = x;
1839 //
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001840 // In particular, we need to re-lookup 'v' (in top_scope_, not
1841 // declaration_scope) as it may be a different 'v' than the 'v' in the
1842 // declaration (e.g., if we are inside a 'with' statement or 'catch'
1843 // block).
Steve Blocka7e24c12009-10-30 11:49:00 +00001844 //
1845 // However, note that const declarations are different! A const
1846 // declaration of the form:
1847 //
1848 // const c = x;
1849 //
1850 // is *not* syntactic sugar for:
1851 //
1852 // const c; c = x;
1853 //
1854 // The "variable" c initialized to x is the same as the declared
1855 // one - there is no re-lookup (see the last parameter of the
1856 // Declare() call above).
1857
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001858 Scope* initialization_scope = is_const ? declaration_scope : top_scope_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001859 Expression* value = NULL;
1860 int position = -1;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001861 // Harmony consts have non-optional initializers.
1862 if (peek() == Token::ASSIGN || mode == CONST_HARMONY) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001863 Expect(Token::ASSIGN, CHECK_OK);
1864 position = scanner().location().beg_pos;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001865 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001866 // Don't infer if it is "a = function(){...}();"-like expression.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001867 if (fni_ != NULL &&
1868 value->AsCall() == NULL &&
1869 value->AsCallNew() == NULL) {
1870 fni_->Infer();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001871 } else {
1872 fni_->RemoveLastFunction();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001873 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001874 if (decl_props != NULL) *decl_props = kHasInitializers;
1875 }
1876
1877 // Record the end position of the initializer.
1878 if (proxy->var() != NULL) {
1879 proxy->var()->set_initializer_position(scanner().location().end_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001880 }
1881
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001882 // Make sure that 'const x' and 'let x' initialize 'x' to undefined.
1883 if (value == NULL && needs_init) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001884 value = GetLiteralUndefined();
1885 }
1886
1887 // Global variable declarations must be compiled in a specific
1888 // way. When the script containing the global variable declaration
1889 // is entered, the global variable must be declared, so that if it
1890 // doesn't exist (not even in a prototype of the global object) it
1891 // gets created with an initial undefined value. This is handled
1892 // by the declarations part of the function representing the
1893 // top-level global code; see Runtime::DeclareGlobalVariable. If
1894 // it already exists (in the object or in a prototype), it is
1895 // *not* touched until the variable declaration statement is
1896 // executed.
1897 //
1898 // Executing the variable declaration statement will always
1899 // guarantee to give the global object a "local" variable; a
1900 // variable defined in the global object and not in any
1901 // prototype. This way, global variable declarations can shadow
1902 // properties in the prototype chain, but only after the variable
1903 // declaration statement has been executed. This is important in
1904 // browsers where the global object (window) has lots of
1905 // properties defined in prototype objects.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001906 if (initialization_scope->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001907 // Compute the arguments for the runtime call.
Ben Murdoch257744e2011-11-30 15:57:28 +00001908 ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001909 // We have at least 1 parameter.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001910 arguments->Add(NewLiteral(name));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001911 CallRuntime* initialize;
1912
1913 if (is_const) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001914 arguments->Add(value);
1915 value = NULL; // zap the value to avoid the unnecessary assignment
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001916
1917 // Construct the call to Runtime_InitializeConstGlobal
1918 // and add it to the initialization statement block.
1919 // Note that the function does different things depending on
1920 // the number of arguments (1 or 2).
Steve Blocka7e24c12009-10-30 11:49:00 +00001921 initialize =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001922 new(zone()) CallRuntime(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001923 isolate(),
1924 isolate()->factory()->InitializeConstGlobal_symbol(),
1925 Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
1926 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001927 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001928 // Add strict mode.
1929 // We may want to pass singleton to avoid Literal allocations.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001930 LanguageMode language_mode = initialization_scope->language_mode();
1931 arguments->Add(NewNumberLiteral(language_mode));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001932
1933 // Be careful not to assign a value to the global variable if
1934 // we're in a with. The initialization value should not
1935 // necessarily be stored in the global object in that case,
1936 // which is why we need to generate a separate assignment node.
1937 if (value != NULL && !inside_with()) {
1938 arguments->Add(value);
1939 value = NULL; // zap the value to avoid the unnecessary assignment
1940 }
1941
1942 // Construct the call to Runtime_InitializeVarGlobal
1943 // and add it to the initialization statement block.
1944 // Note that the function does different things depending on
1945 // the number of arguments (2 or 3).
Steve Blocka7e24c12009-10-30 11:49:00 +00001946 initialize =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001947 new(zone()) CallRuntime(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001948 isolate(),
1949 isolate()->factory()->InitializeVarGlobal_symbol(),
1950 Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
1951 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001952 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001953
Ben Murdoch8b112d22011-06-08 16:22:53 +01001954 block->AddStatement(new(zone()) ExpressionStatement(initialize));
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001955 } else if (needs_init) {
1956 // Constant initializations always assign to the declared constant which
1957 // is always at the function scope level. This is only relevant for
1958 // dynamically looked-up variables and constants (the start context for
1959 // constant lookups is always the function context, while it is the top
1960 // context for var declared variables). Sigh...
1961 // For 'let' and 'const' declared variables in harmony mode the
1962 // initialization also always assigns to the declared variable.
1963 ASSERT(proxy != NULL);
1964 ASSERT(proxy->var() != NULL);
1965 ASSERT(value != NULL);
1966 Assignment* assignment =
1967 new(zone()) Assignment(isolate(), init_op, proxy, value, position);
1968 block->AddStatement(new(zone()) ExpressionStatement(assignment));
1969 value = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001970 }
1971
Ben Murdoch589d6972011-11-30 16:04:58 +00001972 // Add an assignment node to the initialization statement block if we still
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001973 // have a pending initialization value.
Steve Blocka7e24c12009-10-30 11:49:00 +00001974 if (value != NULL) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001975 ASSERT(mode == VAR);
1976 // 'var' initializations are simply assignments (with all the consequences
1977 // if they are inside a 'with' statement - they may change a 'with' object
1978 // property).
1979 VariableProxy* proxy = initialization_scope->NewUnresolved(name);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001980 Assignment* assignment =
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001981 new(zone()) Assignment(isolate(), init_op, proxy, value, position);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001982 block->AddStatement(new(zone()) ExpressionStatement(assignment));
Steve Blocka7e24c12009-10-30 11:49:00 +00001983 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001984
1985 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00001986 } while (peek() == Token::COMMA);
1987
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001988 // If there was a single non-const declaration, return it in the output
1989 // parameter for possible use by for/in.
1990 if (nvars == 1 && !is_const) {
1991 *out = name;
Steve Blocka7e24c12009-10-30 11:49:00 +00001992 }
1993
1994 return block;
1995}
1996
1997
1998static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
1999 ASSERT(!label.is_null());
2000 if (labels != NULL)
2001 for (int i = labels->length(); i-- > 0; )
2002 if (labels->at(i).is_identical_to(label))
2003 return true;
2004
2005 return false;
2006}
2007
2008
2009Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
2010 bool* ok) {
2011 // ExpressionStatement | LabelledStatement ::
2012 // Expression ';'
2013 // Identifier ':' Statement
Steve Block1e0659c2011-05-24 12:43:12 +01002014 bool starts_with_idenfifier = peek_any_identifier();
Steve Blocka7e24c12009-10-30 11:49:00 +00002015 Expression* expr = ParseExpression(true, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002016 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
Steve Blocka7e24c12009-10-30 11:49:00 +00002017 expr->AsVariableProxy() != NULL &&
2018 !expr->AsVariableProxy()->is_this()) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002019 // Expression is a single identifier, and not, e.g., a parenthesized
2020 // identifier.
Steve Blocka7e24c12009-10-30 11:49:00 +00002021 VariableProxy* var = expr->AsVariableProxy();
2022 Handle<String> label = var->name();
2023 // TODO(1240780): We don't check for redeclaration of labels
2024 // during preparsing since keeping track of the set of active
2025 // labels requires nontrivial changes to the way scopes are
2026 // structured. However, these are probably changes we want to
2027 // make later anyway so we should go back and fix this then.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002028 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
Ben Murdoch589d6972011-11-30 16:04:58 +00002029 SmartArrayPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002030 const char* elms[2] = { "Label", *c_string };
2031 Vector<const char*> args(elms, 2);
2032 ReportMessage("redeclaration", args);
2033 *ok = false;
2034 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00002035 }
Ben Murdoch257744e2011-11-30 15:57:28 +00002036 if (labels == NULL) labels = new(zone()) ZoneStringList(4);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002037 labels->Add(label);
2038 // Remove the "ghost" variable that turned out to be a label
2039 // from the top scope. This way, we don't try to resolve it
2040 // during the scope processing.
2041 top_scope_->RemoveUnresolved(var);
Steve Blocka7e24c12009-10-30 11:49:00 +00002042 Expect(Token::COLON, CHECK_OK);
2043 return ParseStatement(labels, ok);
2044 }
2045
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002046 // If we have an extension, we allow a native function declaration.
2047 // A native function declaration starts with "native function" with
2048 // no line-terminator between the two words.
2049 if (extension_ != NULL &&
2050 peek() == Token::FUNCTION &&
2051 !scanner().HasAnyLineTerminatorBeforeNext() &&
2052 expr != NULL &&
2053 expr->AsVariableProxy() != NULL &&
2054 expr->AsVariableProxy()->name()->Equals(
2055 isolate()->heap()->native_symbol()) &&
2056 !scanner().literal_contains_escapes()) {
2057 return ParseNativeDeclaration(ok);
2058 }
2059
Steve Blocka7e24c12009-10-30 11:49:00 +00002060 // Parsed expression statement.
2061 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002062 return new(zone()) ExpressionStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00002063}
2064
2065
2066IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
2067 // IfStatement ::
2068 // 'if' '(' Expression ')' Statement ('else' Statement)?
2069
2070 Expect(Token::IF, CHECK_OK);
2071 Expect(Token::LPAREN, CHECK_OK);
2072 Expression* condition = ParseExpression(true, CHECK_OK);
2073 Expect(Token::RPAREN, CHECK_OK);
2074 Statement* then_statement = ParseStatement(labels, CHECK_OK);
2075 Statement* else_statement = NULL;
2076 if (peek() == Token::ELSE) {
2077 Next();
2078 else_statement = ParseStatement(labels, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002079 } else {
2080 else_statement = EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002081 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002082 return new(zone()) IfStatement(
2083 isolate(), condition, then_statement, else_statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00002084}
2085
2086
2087Statement* Parser::ParseContinueStatement(bool* ok) {
2088 // ContinueStatement ::
2089 // 'continue' Identifier? ';'
2090
2091 Expect(Token::CONTINUE, CHECK_OK);
2092 Handle<String> label = Handle<String>::null();
2093 Token::Value tok = peek();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002094 if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00002095 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2096 label = ParseIdentifier(CHECK_OK);
2097 }
2098 IterationStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002099 target = LookupContinueTarget(label, CHECK_OK);
2100 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002101 // Illegal continue statement.
2102 const char* message = "illegal_continue";
2103 Vector<Handle<String> > args;
2104 if (!label.is_null()) {
2105 message = "unknown_label";
2106 args = Vector<Handle<String> >(&label, 1);
2107 }
2108 ReportMessageAt(scanner().location(), message, args);
2109 *ok = false;
2110 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00002111 }
2112 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002113 return new(zone()) ContinueStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00002114}
2115
2116
2117Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
2118 // BreakStatement ::
2119 // 'break' Identifier? ';'
2120
2121 Expect(Token::BREAK, CHECK_OK);
2122 Handle<String> label;
2123 Token::Value tok = peek();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002124 if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00002125 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2126 label = ParseIdentifier(CHECK_OK);
2127 }
2128 // Parse labeled break statements that target themselves into
2129 // empty statements, e.g. 'l1: l2: l3: break l2;'
2130 if (!label.is_null() && ContainsLabel(labels, label)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002131 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002132 }
2133 BreakableStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002134 target = LookupBreakTarget(label, CHECK_OK);
2135 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002136 // Illegal break statement.
2137 const char* message = "illegal_break";
2138 Vector<Handle<String> > args;
2139 if (!label.is_null()) {
2140 message = "unknown_label";
2141 args = Vector<Handle<String> >(&label, 1);
2142 }
2143 ReportMessageAt(scanner().location(), message, args);
2144 *ok = false;
2145 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00002146 }
2147 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002148 return new(zone()) BreakStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00002149}
2150
2151
2152Statement* Parser::ParseReturnStatement(bool* ok) {
2153 // ReturnStatement ::
2154 // 'return' Expression? ';'
2155
2156 // Consume the return token. It is necessary to do the before
2157 // reporting any errors on it, because of the way errors are
2158 // reported (underlining).
2159 Expect(Token::RETURN, CHECK_OK);
2160
Ben Murdoch692be652012-01-10 18:47:50 +00002161 Token::Value tok = peek();
2162 Statement* result;
2163 if (scanner().HasAnyLineTerminatorBeforeNext() ||
2164 tok == Token::SEMICOLON ||
2165 tok == Token::RBRACE ||
2166 tok == Token::EOS) {
2167 ExpectSemicolon(CHECK_OK);
2168 result = new(zone()) ReturnStatement(GetLiteralUndefined());
2169 } else {
2170 Expression* expr = ParseExpression(true, CHECK_OK);
2171 ExpectSemicolon(CHECK_OK);
2172 result = new(zone()) ReturnStatement(expr);
2173 }
2174
Steve Blocka7e24c12009-10-30 11:49:00 +00002175 // An ECMAScript program is considered syntactically incorrect if it
2176 // contains a return statement that is not within the body of a
2177 // function. See ECMA-262, section 12.9, page 67.
2178 //
2179 // To be consistent with KJS we report the syntax error at runtime.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002180 Scope* declaration_scope = top_scope_->DeclarationScope();
2181 if (declaration_scope->is_global_scope() ||
2182 declaration_scope->is_eval_scope()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002183 Handle<String> type = isolate()->factory()->illegal_return_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002184 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
Ben Murdoch8b112d22011-06-08 16:22:53 +01002185 return new(zone()) ExpressionStatement(throw_error);
Steve Blocka7e24c12009-10-30 11:49:00 +00002186 }
Ben Murdoch692be652012-01-10 18:47:50 +00002187 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00002188}
2189
2190
Steve Blocka7e24c12009-10-30 11:49:00 +00002191Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
2192 // WithStatement ::
2193 // 'with' '(' Expression ')' Statement
2194
2195 Expect(Token::WITH, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002196
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002197 if (!top_scope_->is_classic_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002198 ReportMessage("strict_mode_with", Vector<const char*>::empty());
2199 *ok = false;
2200 return NULL;
2201 }
2202
Steve Blocka7e24c12009-10-30 11:49:00 +00002203 Expect(Token::LPAREN, CHECK_OK);
2204 Expression* expr = ParseExpression(true, CHECK_OK);
2205 Expect(Token::RPAREN, CHECK_OK);
2206
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002207 top_scope_->DeclarationScope()->RecordWithStatement();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002208 Scope* with_scope = NewScope(top_scope_, WITH_SCOPE);
2209 Statement* stmt;
2210 { BlockState block_state(this, with_scope);
2211 with_scope->set_start_position(scanner().peek_location().beg_pos);
2212 stmt = ParseStatement(labels, CHECK_OK);
2213 with_scope->set_end_position(scanner().location().end_pos);
2214 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002215 return new(zone()) WithStatement(expr, stmt);
Steve Blocka7e24c12009-10-30 11:49:00 +00002216}
2217
2218
2219CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
2220 // CaseClause ::
2221 // 'case' Expression ':' Statement*
2222 // 'default' ':' Statement*
2223
2224 Expression* label = NULL; // NULL expression indicates default case
2225 if (peek() == Token::CASE) {
2226 Expect(Token::CASE, CHECK_OK);
2227 label = ParseExpression(true, CHECK_OK);
2228 } else {
2229 Expect(Token::DEFAULT, CHECK_OK);
2230 if (*default_seen_ptr) {
2231 ReportMessage("multiple_defaults_in_switch",
2232 Vector<const char*>::empty());
2233 *ok = false;
2234 return NULL;
2235 }
2236 *default_seen_ptr = true;
2237 }
2238 Expect(Token::COLON, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002239 int pos = scanner().location().beg_pos;
Ben Murdoch257744e2011-11-30 15:57:28 +00002240 ZoneList<Statement*>* statements = new(zone()) ZoneList<Statement*>(5);
Steve Blocka7e24c12009-10-30 11:49:00 +00002241 while (peek() != Token::CASE &&
2242 peek() != Token::DEFAULT &&
2243 peek() != Token::RBRACE) {
2244 Statement* stat = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002245 statements->Add(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00002246 }
2247
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002248 return new(zone()) CaseClause(isolate(), label, statements, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002249}
2250
2251
2252SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
2253 bool* ok) {
2254 // SwitchStatement ::
2255 // 'switch' '(' Expression ')' '{' CaseClause* '}'
2256
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002257 SwitchStatement* statement = new(zone()) SwitchStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002258 Target target(&this->target_stack_, statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00002259
2260 Expect(Token::SWITCH, CHECK_OK);
2261 Expect(Token::LPAREN, CHECK_OK);
2262 Expression* tag = ParseExpression(true, CHECK_OK);
2263 Expect(Token::RPAREN, CHECK_OK);
2264
2265 bool default_seen = false;
Ben Murdoch257744e2011-11-30 15:57:28 +00002266 ZoneList<CaseClause*>* cases = new(zone()) ZoneList<CaseClause*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002267 Expect(Token::LBRACE, CHECK_OK);
2268 while (peek() != Token::RBRACE) {
2269 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002270 cases->Add(clause);
Steve Blocka7e24c12009-10-30 11:49:00 +00002271 }
2272 Expect(Token::RBRACE, CHECK_OK);
2273
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002274 if (statement) statement->Initialize(tag, cases);
Steve Blocka7e24c12009-10-30 11:49:00 +00002275 return statement;
2276}
2277
2278
2279Statement* Parser::ParseThrowStatement(bool* ok) {
2280 // ThrowStatement ::
2281 // 'throw' Expression ';'
2282
2283 Expect(Token::THROW, CHECK_OK);
2284 int pos = scanner().location().beg_pos;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002285 if (scanner().HasAnyLineTerminatorBeforeNext()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002286 ReportMessage("newline_after_throw", Vector<const char*>::empty());
2287 *ok = false;
2288 return NULL;
2289 }
2290 Expression* exception = ParseExpression(true, CHECK_OK);
2291 ExpectSemicolon(CHECK_OK);
2292
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002293 return new(zone()) ExpressionStatement(
2294 new(zone()) Throw(isolate(), exception, pos));
Steve Blocka7e24c12009-10-30 11:49:00 +00002295}
2296
2297
2298TryStatement* Parser::ParseTryStatement(bool* ok) {
2299 // TryStatement ::
2300 // 'try' Block Catch
2301 // 'try' Block Finally
2302 // 'try' Block Catch Finally
2303 //
2304 // Catch ::
2305 // 'catch' '(' Identifier ')' Block
2306 //
2307 // Finally ::
2308 // 'finally' Block
2309
2310 Expect(Token::TRY, CHECK_OK);
2311
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002312 TargetCollector try_collector;
Steve Blocka7e24c12009-10-30 11:49:00 +00002313 Block* try_block;
2314
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002315 { Target target(&this->target_stack_, &try_collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002316 try_block = ParseBlock(NULL, CHECK_OK);
2317 }
2318
Steve Blocka7e24c12009-10-30 11:49:00 +00002319 Token::Value tok = peek();
2320 if (tok != Token::CATCH && tok != Token::FINALLY) {
2321 ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
2322 *ok = false;
2323 return NULL;
2324 }
2325
2326 // If we can break out from the catch block and there is a finally block,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002327 // then we will need to collect escaping targets from the catch
2328 // block. Since we don't know yet if there will be a finally block, we
2329 // always collect the targets.
2330 TargetCollector catch_collector;
2331 Scope* catch_scope = NULL;
2332 Variable* catch_variable = NULL;
2333 Block* catch_block = NULL;
2334 Handle<String> name;
Steve Blocka7e24c12009-10-30 11:49:00 +00002335 if (tok == Token::CATCH) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002336 Consume(Token::CATCH);
2337
2338 Expect(Token::LPAREN, CHECK_OK);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002339 catch_scope = NewScope(top_scope_, CATCH_SCOPE);
2340 catch_scope->set_start_position(scanner().location().beg_pos);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002341 name = ParseIdentifier(CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002342
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002343 if (!top_scope_->is_classic_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01002344 ReportMessage("strict_catch_variable", Vector<const char*>::empty());
2345 *ok = false;
2346 return NULL;
2347 }
2348
Steve Blocka7e24c12009-10-30 11:49:00 +00002349 Expect(Token::RPAREN, CHECK_OK);
2350
2351 if (peek() == Token::LBRACE) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002352 Target target(&this->target_stack_, &catch_collector);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002353 VariableMode mode = is_extended_mode() ? LET : VAR;
2354 catch_variable =
2355 catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002356
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002357 BlockState block_state(this, catch_scope);
Ben Murdoch589d6972011-11-30 16:04:58 +00002358 catch_block = ParseBlock(NULL, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002359 } else {
2360 Expect(Token::LBRACE, CHECK_OK);
2361 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002362 catch_scope->set_end_position(scanner().location().end_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002363 tok = peek();
2364 }
2365
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002366 Block* finally_block = NULL;
2367 if (tok == Token::FINALLY || catch_block == NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002368 Consume(Token::FINALLY);
Steve Blocka7e24c12009-10-30 11:49:00 +00002369 finally_block = ParseBlock(NULL, CHECK_OK);
2370 }
2371
2372 // Simplify the AST nodes by converting:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002373 // 'try B0 catch B1 finally B2'
Steve Blocka7e24c12009-10-30 11:49:00 +00002374 // to:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002375 // 'try { try B0 catch B1 } finally B2'
Steve Blocka7e24c12009-10-30 11:49:00 +00002376
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002377 if (catch_block != NULL && finally_block != NULL) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002378 // If we have both, create an inner try/catch.
2379 ASSERT(catch_scope != NULL && catch_variable != NULL);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002380 int index = current_function_state_->NextHandlerIndex();
2381 TryCatchStatement* statement = new(zone()) TryCatchStatement(index,
2382 try_block,
2383 catch_scope,
2384 catch_variable,
2385 catch_block);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002386 statement->set_escaping_targets(try_collector.targets());
2387 try_block = new(zone()) Block(isolate(), NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00002388 try_block->AddStatement(statement);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002389 catch_block = NULL; // Clear to indicate it's been handled.
Steve Blocka7e24c12009-10-30 11:49:00 +00002390 }
2391
2392 TryStatement* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002393 if (catch_block != NULL) {
2394 ASSERT(finally_block == NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002395 ASSERT(catch_scope != NULL && catch_variable != NULL);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002396 int index = current_function_state_->NextHandlerIndex();
2397 result = new(zone()) TryCatchStatement(index,
2398 try_block,
2399 catch_scope,
2400 catch_variable,
2401 catch_block);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002402 } else {
2403 ASSERT(finally_block != NULL);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002404 int index = current_function_state_->NextHandlerIndex();
2405 result = new(zone()) TryFinallyStatement(index,
2406 try_block,
2407 finally_block);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002408 // Combine the jump targets of the try block and the possible catch block.
2409 try_collector.targets()->AddAll(*catch_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002410 }
2411
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002412 result->set_escaping_targets(try_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002413 return result;
2414}
2415
2416
Steve Block3ce2e202009-11-05 08:53:23 +00002417DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
2418 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002419 // DoStatement ::
2420 // 'do' Statement 'while' '(' Expression ')' ';'
2421
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002422 DoWhileStatement* loop = new(zone()) DoWhileStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002423 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002424
2425 Expect(Token::DO, CHECK_OK);
2426 Statement* body = ParseStatement(NULL, CHECK_OK);
2427 Expect(Token::WHILE, CHECK_OK);
2428 Expect(Token::LPAREN, CHECK_OK);
Steve Blockd0582a62009-12-15 09:54:21 +00002429
2430 if (loop != NULL) {
2431 int position = scanner().location().beg_pos;
2432 loop->set_condition_position(position);
2433 }
2434
Steve Blocka7e24c12009-10-30 11:49:00 +00002435 Expression* cond = ParseExpression(true, CHECK_OK);
2436 Expect(Token::RPAREN, CHECK_OK);
2437
2438 // Allow do-statements to be terminated with and without
2439 // semi-colons. This allows code such as 'do;while(0)return' to
2440 // parse, which would not be the case if we had used the
2441 // ExpectSemicolon() functionality here.
2442 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2443
Steve Block3ce2e202009-11-05 08:53:23 +00002444 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002445 return loop;
2446}
2447
2448
Steve Block3ce2e202009-11-05 08:53:23 +00002449WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002450 // WhileStatement ::
2451 // 'while' '(' Expression ')' Statement
2452
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002453 WhileStatement* loop = new(zone()) WhileStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002454 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002455
2456 Expect(Token::WHILE, CHECK_OK);
2457 Expect(Token::LPAREN, CHECK_OK);
2458 Expression* cond = ParseExpression(true, CHECK_OK);
2459 Expect(Token::RPAREN, CHECK_OK);
2460 Statement* body = ParseStatement(NULL, CHECK_OK);
2461
Steve Block3ce2e202009-11-05 08:53:23 +00002462 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002463 return loop;
2464}
2465
2466
2467Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
2468 // ForStatement ::
2469 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
2470
2471 Statement* init = NULL;
2472
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002473 // Create an in-between scope for let-bound iteration variables.
2474 Scope* saved_scope = top_scope_;
2475 Scope* for_scope = NewScope(top_scope_, BLOCK_SCOPE);
2476 top_scope_ = for_scope;
2477
Steve Blocka7e24c12009-10-30 11:49:00 +00002478 Expect(Token::FOR, CHECK_OK);
2479 Expect(Token::LPAREN, CHECK_OK);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002480 for_scope->set_start_position(scanner().location().beg_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002481 if (peek() != Token::SEMICOLON) {
2482 if (peek() == Token::VAR || peek() == Token::CONST) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002483 Handle<String> name;
Steve Blocka7e24c12009-10-30 11:49:00 +00002484 Block* variable_statement =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002485 ParseVariableDeclarations(kForStatement, NULL, &name, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002486
2487 if (peek() == Token::IN && !name.is_null()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002488 VariableProxy* each = top_scope_->NewUnresolved(name);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002489 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002490 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002491
2492 Expect(Token::IN, CHECK_OK);
2493 Expression* enumerable = ParseExpression(true, CHECK_OK);
2494 Expect(Token::RPAREN, CHECK_OK);
2495
2496 Statement* body = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002497 loop->Initialize(each, enumerable, body);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002498 Block* result = new(zone()) Block(isolate(), NULL, 2, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002499 result->AddStatement(variable_statement);
2500 result->AddStatement(loop);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002501 top_scope_ = saved_scope;
2502 for_scope->set_end_position(scanner().location().end_pos);
2503 for_scope = for_scope->FinalizeBlockScope();
2504 ASSERT(for_scope == NULL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002505 // Parsed for-in loop w/ variable/const declaration.
2506 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00002507 } else {
2508 init = variable_statement;
2509 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002510 } else if (peek() == Token::LET) {
2511 Handle<String> name;
2512 VariableDeclarationProperties decl_props = kHasNoInitializers;
2513 Block* variable_statement =
2514 ParseVariableDeclarations(kForStatement,
2515 &decl_props,
2516 &name,
2517 CHECK_OK);
2518 bool accept_IN = !name.is_null() && decl_props != kHasInitializers;
2519 if (peek() == Token::IN && accept_IN) {
2520 // Rewrite a for-in statement of the form
2521 //
2522 // for (let x in e) b
2523 //
2524 // into
2525 //
2526 // <let x' be a temporary variable>
2527 // for (x' in e) {
2528 // let x;
2529 // x = x';
2530 // b;
2531 // }
Steve Blocka7e24c12009-10-30 11:49:00 +00002532
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002533 // TODO(keuchel): Move the temporary variable to the block scope, after
2534 // implementing stack allocated block scoped variables.
2535 Variable* temp = top_scope_->DeclarationScope()->NewTemporary(name);
2536 VariableProxy* temp_proxy = new(zone()) VariableProxy(isolate(), temp);
2537 VariableProxy* each = top_scope_->NewUnresolved(name);
2538 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
2539 Target target(&this->target_stack_, loop);
2540
2541 Expect(Token::IN, CHECK_OK);
2542 Expression* enumerable = ParseExpression(true, CHECK_OK);
2543 Expect(Token::RPAREN, CHECK_OK);
2544
2545 Statement* body = ParseStatement(NULL, CHECK_OK);
2546 Block* body_block = new(zone()) Block(isolate(), NULL, 3, false);
2547 Assignment* assignment = new(zone()) Assignment(isolate(),
2548 Token::ASSIGN,
2549 each,
2550 temp_proxy,
2551 RelocInfo::kNoPosition);
2552 Statement* assignment_statement =
2553 new(zone()) ExpressionStatement(assignment);
2554 body_block->AddStatement(variable_statement);
2555 body_block->AddStatement(assignment_statement);
2556 body_block->AddStatement(body);
2557 loop->Initialize(temp_proxy, enumerable, body_block);
2558 top_scope_ = saved_scope;
2559 for_scope->set_end_position(scanner().location().end_pos);
2560 for_scope = for_scope->FinalizeBlockScope();
2561 body_block->set_block_scope(for_scope);
2562 // Parsed for-in loop w/ let declaration.
2563 return loop;
2564
2565 } else {
2566 init = variable_statement;
2567 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002568 } else {
2569 Expression* expression = ParseExpression(false, CHECK_OK);
2570 if (peek() == Token::IN) {
2571 // Signal a reference error if the expression is an invalid
2572 // left-hand side expression. We could report this as a syntax
2573 // error here but for compatibility with JSC we choose to report
2574 // the error at runtime.
2575 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002576 Handle<String> type =
2577 isolate()->factory()->invalid_lhs_in_for_in_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002578 expression = NewThrowReferenceError(type);
2579 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002580 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002581 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002582
2583 Expect(Token::IN, CHECK_OK);
2584 Expression* enumerable = ParseExpression(true, CHECK_OK);
2585 Expect(Token::RPAREN, CHECK_OK);
2586
2587 Statement* body = ParseStatement(NULL, CHECK_OK);
2588 if (loop) loop->Initialize(expression, enumerable, body);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002589 top_scope_ = saved_scope;
2590 for_scope->set_end_position(scanner().location().end_pos);
2591 for_scope = for_scope->FinalizeBlockScope();
2592 ASSERT(for_scope == NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00002593 // Parsed for-in loop.
2594 return loop;
2595
2596 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002597 init = new(zone()) ExpressionStatement(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002598 }
2599 }
2600 }
2601
2602 // Standard 'for' loop
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002603 ForStatement* loop = new(zone()) ForStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002604 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002605
2606 // Parsed initializer at this point.
2607 Expect(Token::SEMICOLON, CHECK_OK);
2608
2609 Expression* cond = NULL;
2610 if (peek() != Token::SEMICOLON) {
2611 cond = ParseExpression(true, CHECK_OK);
2612 }
2613 Expect(Token::SEMICOLON, CHECK_OK);
2614
2615 Statement* next = NULL;
2616 if (peek() != Token::RPAREN) {
2617 Expression* exp = ParseExpression(true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002618 next = new(zone()) ExpressionStatement(exp);
Steve Blocka7e24c12009-10-30 11:49:00 +00002619 }
2620 Expect(Token::RPAREN, CHECK_OK);
2621
2622 Statement* body = ParseStatement(NULL, CHECK_OK);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002623 top_scope_ = saved_scope;
2624 for_scope->set_end_position(scanner().location().end_pos);
2625 for_scope = for_scope->FinalizeBlockScope();
2626 if (for_scope != NULL) {
2627 // Rewrite a for statement of the form
2628 //
2629 // for (let x = i; c; n) b
2630 //
2631 // into
2632 //
2633 // {
2634 // let x = i;
2635 // for (; c; n) b
2636 // }
2637 ASSERT(init != NULL);
2638 Block* result = new(zone()) Block(isolate(), NULL, 2, false);
2639 result->AddStatement(init);
2640 result->AddStatement(loop);
2641 result->set_block_scope(for_scope);
2642 if (loop) loop->Initialize(NULL, cond, next, body);
2643 return result;
2644 } else {
2645 if (loop) loop->Initialize(init, cond, next, body);
2646 return loop;
2647 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002648}
2649
2650
2651// Precedence = 1
2652Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
2653 // Expression ::
2654 // AssignmentExpression
2655 // Expression ',' AssignmentExpression
2656
2657 Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
2658 while (peek() == Token::COMMA) {
2659 Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002660 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002661 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002662 result = new(zone()) BinaryOperation(
2663 isolate(), Token::COMMA, result, right, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002664 }
2665 return result;
2666}
2667
2668
2669// Precedence = 2
2670Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
2671 // AssignmentExpression ::
2672 // ConditionalExpression
2673 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2674
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002675 if (fni_ != NULL) fni_->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00002676 Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
2677
2678 if (!Token::IsAssignmentOp(peek())) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002679 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00002680 // Parsed conditional expression only (no assignment).
2681 return expression;
2682 }
2683
2684 // Signal a reference error if the expression is an invalid left-hand
2685 // side expression. We could report this as a syntax error here but
2686 // for compatibility with JSC we choose to report the error at
2687 // runtime.
2688 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002689 Handle<String> type =
2690 isolate()->factory()->invalid_lhs_in_assignment_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002691 expression = NewThrowReferenceError(type);
2692 }
2693
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002694 if (!top_scope_->is_classic_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002695 // Assignment to eval or arguments is disallowed in strict mode.
2696 CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
2697 }
2698
Steve Blocka7e24c12009-10-30 11:49:00 +00002699 Token::Value op = Next(); // Get assignment operator.
2700 int pos = scanner().location().beg_pos;
2701 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2702
2703 // TODO(1231235): We try to estimate the set of properties set by
2704 // constructors. We define a new property whenever there is an
2705 // assignment to a property of 'this'. We should probably only add
2706 // properties if we haven't seen them before. Otherwise we'll
2707 // probably overestimate the number of properties.
2708 Property* property = expression ? expression->AsProperty() : NULL;
2709 if (op == Token::ASSIGN &&
2710 property != NULL &&
2711 property->obj()->AsVariableProxy() != NULL &&
2712 property->obj()->AsVariableProxy()->is_this()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002713 current_function_state_->AddProperty();
Steve Blocka7e24c12009-10-30 11:49:00 +00002714 }
2715
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002716 // If we assign a function literal to a property we pretenure the
2717 // literal so it can be added as a constant function property.
2718 if (property != NULL && right->AsFunctionLiteral() != NULL) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002719 right->AsFunctionLiteral()->set_pretenure();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002720 }
2721
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002722 if (fni_ != NULL) {
2723 // Check if the right hand side is a call to avoid inferring a
2724 // name if we're dealing with "a = function(){...}();"-like
2725 // expression.
2726 if ((op == Token::INIT_VAR
2727 || op == Token::INIT_CONST
2728 || op == Token::ASSIGN)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002729 && (right->AsCall() == NULL && right->AsCallNew() == NULL)) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002730 fni_->Infer();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002731 } else {
2732 fni_->RemoveLastFunction();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002733 }
2734 fni_->Leave();
2735 }
2736
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002737 return new(zone()) Assignment(isolate(), op, expression, right, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002738}
2739
2740
2741// Precedence = 3
2742Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
2743 // ConditionalExpression ::
2744 // LogicalOrExpression
2745 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
2746
2747 // We start using the binary expression parser for prec >= 4 only!
2748 Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
2749 if (peek() != Token::CONDITIONAL) return expression;
2750 Consume(Token::CONDITIONAL);
2751 // In parsing the first assignment expression in conditional
2752 // expressions we always accept the 'in' keyword; see ECMA-262,
2753 // section 11.12, page 58.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002754 int left_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002755 Expression* left = ParseAssignmentExpression(true, CHECK_OK);
2756 Expect(Token::COLON, CHECK_OK);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002757 int right_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002758 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002759 return new(zone()) Conditional(
2760 isolate(), expression, left, right, left_position, right_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002761}
2762
2763
2764static int Precedence(Token::Value tok, bool accept_IN) {
2765 if (tok == Token::IN && !accept_IN)
2766 return 0; // 0 precedence will terminate binary expression parsing
2767
2768 return Token::Precedence(tok);
2769}
2770
2771
2772// Precedence >= 4
2773Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
2774 ASSERT(prec >= 4);
2775 Expression* x = ParseUnaryExpression(CHECK_OK);
2776 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
2777 // prec1 >= 4
2778 while (Precedence(peek(), accept_IN) == prec1) {
2779 Token::Value op = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002780 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002781 Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
2782
2783 // Compute some expressions involving only number literals.
2784 if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
2785 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
2786 double x_val = x->AsLiteral()->handle()->Number();
2787 double y_val = y->AsLiteral()->handle()->Number();
2788
2789 switch (op) {
2790 case Token::ADD:
2791 x = NewNumberLiteral(x_val + y_val);
2792 continue;
2793 case Token::SUB:
2794 x = NewNumberLiteral(x_val - y_val);
2795 continue;
2796 case Token::MUL:
2797 x = NewNumberLiteral(x_val * y_val);
2798 continue;
2799 case Token::DIV:
2800 x = NewNumberLiteral(x_val / y_val);
2801 continue;
2802 case Token::BIT_OR:
2803 x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
2804 continue;
2805 case Token::BIT_AND:
2806 x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
2807 continue;
2808 case Token::BIT_XOR:
2809 x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
2810 continue;
2811 case Token::SHL: {
2812 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
2813 x = NewNumberLiteral(value);
2814 continue;
2815 }
2816 case Token::SHR: {
2817 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2818 uint32_t value = DoubleToUint32(x_val) >> shift;
2819 x = NewNumberLiteral(value);
2820 continue;
2821 }
2822 case Token::SAR: {
2823 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2824 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
2825 x = NewNumberLiteral(value);
2826 continue;
2827 }
2828 default:
2829 break;
2830 }
2831 }
2832
Steve Blocka7e24c12009-10-30 11:49:00 +00002833 // For now we distinguish between comparisons and other binary
2834 // operations. (We could combine the two and get rid of this
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002835 // code and AST node eventually.)
Steve Blocka7e24c12009-10-30 11:49:00 +00002836 if (Token::IsCompareOp(op)) {
2837 // We have a comparison.
2838 Token::Value cmp = op;
2839 switch (op) {
2840 case Token::NE: cmp = Token::EQ; break;
2841 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
2842 default: break;
2843 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002844 x = new(zone()) CompareOperation(isolate(), cmp, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002845 if (cmp != op) {
2846 // The comparison was negated - add a NOT.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002847 x = new(zone()) UnaryOperation(isolate(), Token::NOT, x, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002848 }
2849
2850 } else {
2851 // We have a "normal" binary operation.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002852 x = new(zone()) BinaryOperation(isolate(), op, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002853 }
2854 }
2855 }
2856 return x;
2857}
2858
2859
2860Expression* Parser::ParseUnaryExpression(bool* ok) {
2861 // UnaryExpression ::
2862 // PostfixExpression
2863 // 'delete' UnaryExpression
2864 // 'void' UnaryExpression
2865 // 'typeof' UnaryExpression
2866 // '++' UnaryExpression
2867 // '--' UnaryExpression
2868 // '+' UnaryExpression
2869 // '-' UnaryExpression
2870 // '~' UnaryExpression
2871 // '!' UnaryExpression
2872
2873 Token::Value op = peek();
2874 if (Token::IsUnaryOp(op)) {
2875 op = Next();
Ben Murdoch257744e2011-11-30 15:57:28 +00002876 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002877 Expression* expression = ParseUnaryExpression(CHECK_OK);
2878
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002879 if (expression != NULL && (expression->AsLiteral() != NULL)) {
2880 Handle<Object> literal = expression->AsLiteral()->handle();
2881 if (op == Token::NOT) {
2882 // Convert the literal to a boolean condition and negate it.
2883 bool condition = literal->ToBoolean()->IsTrue();
2884 Handle<Object> result(isolate()->heap()->ToBoolean(!condition));
2885 return NewLiteral(result);
2886 } else if (literal->IsNumber()) {
2887 // Compute some expressions involving only number literals.
2888 double value = literal->Number();
2889 switch (op) {
2890 case Token::ADD:
2891 return expression;
2892 case Token::SUB:
2893 return NewNumberLiteral(-value);
2894 case Token::BIT_NOT:
2895 return NewNumberLiteral(~DoubleToInt32(value));
2896 default:
2897 break;
2898 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002899 }
2900 }
2901
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002902 // "delete identifier" is a syntax error in strict mode.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002903 if (op == Token::DELETE && !top_scope_->is_classic_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002904 VariableProxy* operand = expression->AsVariableProxy();
2905 if (operand != NULL && !operand->is_this()) {
2906 ReportMessage("strict_delete", Vector<const char*>::empty());
2907 *ok = false;
2908 return NULL;
2909 }
2910 }
2911
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002912 return new(zone()) UnaryOperation(isolate(), op, expression, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002913
2914 } else if (Token::IsCountOp(op)) {
2915 op = Next();
2916 Expression* expression = ParseUnaryExpression(CHECK_OK);
2917 // Signal a reference error if the expression is an invalid
2918 // left-hand side expression. We could report this as a syntax
2919 // error here but for compatibility with JSC we choose to report the
2920 // error at runtime.
2921 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002922 Handle<String> type =
2923 isolate()->factory()->invalid_lhs_in_prefix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002924 expression = NewThrowReferenceError(type);
2925 }
Steve Block1e0659c2011-05-24 12:43:12 +01002926
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002927 if (!top_scope_->is_classic_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002928 // Prefix expression operand in strict mode may not be eval or arguments.
2929 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2930 }
2931
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002932 int position = scanner().location().beg_pos;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002933 return new(zone()) CountOperation(isolate(),
2934 op,
Ben Murdoch8b112d22011-06-08 16:22:53 +01002935 true /* prefix */,
2936 expression,
2937 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002938
2939 } else {
2940 return ParsePostfixExpression(ok);
2941 }
2942}
2943
2944
2945Expression* Parser::ParsePostfixExpression(bool* ok) {
2946 // PostfixExpression ::
2947 // LeftHandSideExpression ('++' | '--')?
2948
2949 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002950 if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Ben Murdochb0fe1622011-05-05 13:52:32 +01002951 Token::IsCountOp(peek())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002952 // Signal a reference error if the expression is an invalid
2953 // left-hand side expression. We could report this as a syntax
2954 // error here but for compatibility with JSC we choose to report the
2955 // error at runtime.
2956 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002957 Handle<String> type =
2958 isolate()->factory()->invalid_lhs_in_postfix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002959 expression = NewThrowReferenceError(type);
2960 }
Steve Block1e0659c2011-05-24 12:43:12 +01002961
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002962 if (!top_scope_->is_classic_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002963 // Postfix expression operand in strict mode may not be eval or arguments.
2964 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2965 }
2966
Steve Blocka7e24c12009-10-30 11:49:00 +00002967 Token::Value next = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002968 int position = scanner().location().beg_pos;
Ben Murdoch8b112d22011-06-08 16:22:53 +01002969 expression =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002970 new(zone()) CountOperation(isolate(),
2971 next,
Ben Murdoch8b112d22011-06-08 16:22:53 +01002972 false /* postfix */,
2973 expression,
2974 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002975 }
2976 return expression;
2977}
2978
2979
2980Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
2981 // LeftHandSideExpression ::
2982 // (NewExpression | MemberExpression) ...
2983
2984 Expression* result;
2985 if (peek() == Token::NEW) {
2986 result = ParseNewExpression(CHECK_OK);
2987 } else {
2988 result = ParseMemberExpression(CHECK_OK);
2989 }
2990
2991 while (true) {
2992 switch (peek()) {
2993 case Token::LBRACK: {
2994 Consume(Token::LBRACK);
2995 int pos = scanner().location().beg_pos;
2996 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002997 result = new(zone()) Property(isolate(), result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002998 Expect(Token::RBRACK, CHECK_OK);
2999 break;
3000 }
3001
3002 case Token::LPAREN: {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003003 int pos;
3004 if (scanner().current_token() == Token::IDENTIFIER) {
3005 // For call of an identifier we want to report position of
3006 // the identifier as position of the call in the stack trace.
3007 pos = scanner().location().beg_pos;
3008 } else {
3009 // For other kinds of calls we record position of the parenthesis as
3010 // position of the call. Note that this is extremely important for
3011 // expressions of the form function(){...}() for which call position
3012 // should not point to the closing brace otherwise it will intersect
3013 // with positions recorded for function literal and confuse debugger.
3014 pos = scanner().peek_location().beg_pos;
3015 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003016 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
3017
3018 // Keep track of eval() calls since they disable all local variable
3019 // optimizations.
3020 // The calls that need special treatment are the
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003021 // direct eval calls. These calls are all of the form eval(...), with
3022 // no explicit receiver.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003023 // These calls are marked as potentially direct eval calls. Whether
3024 // they are actually direct calls to eval is determined at run time.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003025 VariableProxy* callee = result->AsVariableProxy();
Steve Block44f0eee2011-05-26 01:26:41 +01003026 if (callee != NULL &&
3027 callee->IsVariable(isolate()->factory()->eval_symbol())) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003028 top_scope_->DeclarationScope()->RecordEvalCall();
Steve Blocka7e24c12009-10-30 11:49:00 +00003029 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003030 result = NewCall(result, args, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00003031 break;
3032 }
3033
3034 case Token::PERIOD: {
3035 Consume(Token::PERIOD);
3036 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01003037 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003038 result = new(zone()) Property(isolate(),
3039 result,
3040 NewLiteral(name),
3041 pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003042 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003043 break;
3044 }
3045
3046 default:
3047 return result;
3048 }
3049 }
3050}
3051
3052
Steve Blocka7e24c12009-10-30 11:49:00 +00003053Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
3054 // NewExpression ::
3055 // ('new')+ MemberExpression
3056
3057 // The grammar for new expressions is pretty warped. The keyword
3058 // 'new' can either be a part of the new expression (where it isn't
3059 // followed by an argument list) or a part of the member expression,
3060 // where it must be followed by an argument list. To accommodate
3061 // this, we parse the 'new' keywords greedily and keep track of how
3062 // many we have parsed. This information is then passed on to the
3063 // member expression parser, which is only allowed to match argument
3064 // lists as long as it has 'new' prefixes left
3065 Expect(Token::NEW, CHECK_OK);
3066 PositionStack::Element pos(stack, scanner().location().beg_pos);
3067
3068 Expression* result;
3069 if (peek() == Token::NEW) {
3070 result = ParseNewPrefix(stack, CHECK_OK);
3071 } else {
3072 result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
3073 }
3074
3075 if (!stack->is_empty()) {
3076 int last = stack->pop();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003077 result = new(zone()) CallNew(isolate(),
3078 result,
Ben Murdoch257744e2011-11-30 15:57:28 +00003079 new(zone()) ZoneList<Expression*>(0),
3080 last);
Steve Blocka7e24c12009-10-30 11:49:00 +00003081 }
3082 return result;
3083}
3084
3085
3086Expression* Parser::ParseNewExpression(bool* ok) {
3087 PositionStack stack(ok);
3088 return ParseNewPrefix(&stack, ok);
3089}
3090
3091
3092Expression* Parser::ParseMemberExpression(bool* ok) {
3093 return ParseMemberWithNewPrefixesExpression(NULL, ok);
3094}
3095
3096
3097Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
3098 bool* ok) {
3099 // MemberExpression ::
3100 // (PrimaryExpression | FunctionLiteral)
3101 // ('[' Expression ']' | '.' Identifier | Arguments)*
3102
3103 // Parse the initial primary or function expression.
3104 Expression* result = NULL;
3105 if (peek() == Token::FUNCTION) {
3106 Expect(Token::FUNCTION, CHECK_OK);
3107 int function_token_position = scanner().location().beg_pos;
3108 Handle<String> name;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003109 bool is_strict_reserved_name = false;
Steve Block1e0659c2011-05-24 12:43:12 +01003110 if (peek_any_identifier()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003111 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
3112 CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003113 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003114 FunctionLiteral::Type type = name.is_null()
3115 ? FunctionLiteral::ANONYMOUS_EXPRESSION
3116 : FunctionLiteral::NAMED_EXPRESSION;
3117 result = ParseFunctionLiteral(name,
3118 is_strict_reserved_name,
3119 function_token_position,
3120 type,
3121 CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003122 } else {
3123 result = ParsePrimaryExpression(CHECK_OK);
3124 }
3125
3126 while (true) {
3127 switch (peek()) {
3128 case Token::LBRACK: {
3129 Consume(Token::LBRACK);
3130 int pos = scanner().location().beg_pos;
3131 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003132 result = new(zone()) Property(isolate(), result, index, pos);
3133 if (fni_ != NULL) {
3134 if (index->IsPropertyName()) {
3135 fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
3136 } else {
3137 fni_->PushLiteralName(
3138 isolate()->factory()->anonymous_function_symbol());
3139 }
3140 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003141 Expect(Token::RBRACK, CHECK_OK);
3142 break;
3143 }
3144 case Token::PERIOD: {
3145 Consume(Token::PERIOD);
3146 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01003147 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003148 result = new(zone()) Property(isolate(),
3149 result,
3150 NewLiteral(name),
3151 pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003152 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003153 break;
3154 }
3155 case Token::LPAREN: {
3156 if ((stack == NULL) || stack->is_empty()) return result;
3157 // Consume one of the new prefixes (already parsed).
3158 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
3159 int last = stack->pop();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003160 result = new(zone()) CallNew(isolate(), result, args, last);
Steve Blocka7e24c12009-10-30 11:49:00 +00003161 break;
3162 }
3163 default:
3164 return result;
3165 }
3166 }
3167}
3168
3169
3170DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
3171 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
3172 // contexts this is used as a statement which invokes the debugger as i a
3173 // break point is present.
3174 // DebuggerStatement ::
3175 // 'debugger' ';'
3176
3177 Expect(Token::DEBUGGER, CHECK_OK);
3178 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003179 return new(zone()) DebuggerStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00003180}
3181
3182
3183void Parser::ReportUnexpectedToken(Token::Value token) {
3184 // We don't report stack overflows here, to avoid increasing the
3185 // stack depth even further. Instead we report it after parsing is
Leon Clarke4515c472010-02-03 11:58:03 +00003186 // over, in ParseProgram/ParseJson.
Ben Murdochb0fe1622011-05-05 13:52:32 +01003187 if (token == Token::ILLEGAL && stack_overflow_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00003188 // Four of the tokens are treated specially
3189 switch (token) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003190 case Token::EOS:
3191 return ReportMessage("unexpected_eos", Vector<const char*>::empty());
3192 case Token::NUMBER:
3193 return ReportMessage("unexpected_token_number",
3194 Vector<const char*>::empty());
3195 case Token::STRING:
3196 return ReportMessage("unexpected_token_string",
3197 Vector<const char*>::empty());
3198 case Token::IDENTIFIER:
3199 return ReportMessage("unexpected_token_identifier",
3200 Vector<const char*>::empty());
Steve Block1e0659c2011-05-24 12:43:12 +01003201 case Token::FUTURE_RESERVED_WORD:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003202 return ReportMessage("unexpected_reserved",
3203 Vector<const char*>::empty());
3204 case Token::FUTURE_STRICT_RESERVED_WORD:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003205 return ReportMessage(top_scope_->is_classic_mode() ?
3206 "unexpected_token_identifier" :
3207 "unexpected_strict_reserved",
Steve Block1e0659c2011-05-24 12:43:12 +01003208 Vector<const char*>::empty());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003209 default:
3210 const char* name = Token::String(token);
3211 ASSERT(name != NULL);
3212 ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00003213 }
3214}
3215
3216
Leon Clarkeac952652010-07-15 11:15:24 +01003217void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003218 SmartArrayPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
Leon Clarkeac952652010-07-15 11:15:24 +01003219 const char* element[1] = { *name_string };
3220 ReportMessage("invalid_preparser_data",
3221 Vector<const char*>(element, 1));
3222 *ok = false;
3223}
3224
3225
Steve Blocka7e24c12009-10-30 11:49:00 +00003226Expression* Parser::ParsePrimaryExpression(bool* ok) {
3227 // PrimaryExpression ::
3228 // 'this'
3229 // 'null'
3230 // 'true'
3231 // 'false'
3232 // Identifier
3233 // Number
3234 // String
3235 // ArrayLiteral
3236 // ObjectLiteral
3237 // RegExpLiteral
3238 // '(' Expression ')'
3239
3240 Expression* result = NULL;
3241 switch (peek()) {
3242 case Token::THIS: {
3243 Consume(Token::THIS);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003244 result = new(zone()) VariableProxy(isolate(), top_scope_->receiver());
Steve Blocka7e24c12009-10-30 11:49:00 +00003245 break;
3246 }
3247
3248 case Token::NULL_LITERAL:
3249 Consume(Token::NULL_LITERAL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003250 result = new(zone()) Literal(
3251 isolate(), isolate()->factory()->null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003252 break;
3253
3254 case Token::TRUE_LITERAL:
3255 Consume(Token::TRUE_LITERAL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003256 result = new(zone()) Literal(
3257 isolate(), isolate()->factory()->true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003258 break;
3259
3260 case Token::FALSE_LITERAL:
3261 Consume(Token::FALSE_LITERAL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003262 result = new(zone()) Literal(
3263 isolate(), isolate()->factory()->false_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003264 break;
3265
Steve Block1e0659c2011-05-24 12:43:12 +01003266 case Token::IDENTIFIER:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003267 case Token::FUTURE_STRICT_RESERVED_WORD: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003268 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003269 if (fni_ != NULL) fni_->PushVariableName(name);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003270 result = top_scope_->NewUnresolved(name, scanner().location().beg_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00003271 break;
3272 }
3273
3274 case Token::NUMBER: {
3275 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003276 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01003277 double value = StringToDouble(isolate()->unicode_cache(),
3278 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01003279 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003280 result = NewNumberLiteral(value);
3281 break;
3282 }
3283
3284 case Token::STRING: {
3285 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003286 Handle<String> symbol = GetSymbol(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003287 result = NewLiteral(symbol);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003288 if (fni_ != NULL) fni_->PushLiteralName(symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00003289 break;
3290 }
3291
3292 case Token::ASSIGN_DIV:
3293 result = ParseRegExpLiteral(true, CHECK_OK);
3294 break;
3295
3296 case Token::DIV:
3297 result = ParseRegExpLiteral(false, CHECK_OK);
3298 break;
3299
3300 case Token::LBRACK:
3301 result = ParseArrayLiteral(CHECK_OK);
3302 break;
3303
3304 case Token::LBRACE:
3305 result = ParseObjectLiteral(CHECK_OK);
3306 break;
3307
3308 case Token::LPAREN:
3309 Consume(Token::LPAREN);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003310 // Heuristically try to detect immediately called functions before
3311 // seeing the call parentheses.
3312 parenthesized_function_ = (peek() == Token::FUNCTION);
Steve Blocka7e24c12009-10-30 11:49:00 +00003313 result = ParseExpression(true, CHECK_OK);
3314 Expect(Token::RPAREN, CHECK_OK);
3315 break;
3316
3317 case Token::MOD:
3318 if (allow_natives_syntax_ || extension_ != NULL) {
3319 result = ParseV8Intrinsic(CHECK_OK);
3320 break;
3321 }
3322 // If we're not allowing special syntax we fall-through to the
3323 // default case.
3324
3325 default: {
Ben Murdochbb769b22010-08-11 14:56:33 +01003326 Token::Value tok = Next();
Steve Blocka7e24c12009-10-30 11:49:00 +00003327 ReportUnexpectedToken(tok);
3328 *ok = false;
3329 return NULL;
3330 }
3331 }
3332
3333 return result;
3334}
3335
3336
Leon Clarke4515c472010-02-03 11:58:03 +00003337void Parser::BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* values,
3338 Handle<FixedArray> literals,
3339 bool* is_simple,
3340 int* depth) {
3341 // Fill in the literals.
3342 // Accumulate output values in local variables.
3343 bool is_simple_acc = true;
3344 int depth_acc = 1;
3345 for (int i = 0; i < values->length(); i++) {
3346 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
3347 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3348 depth_acc = m_literal->depth() + 1;
3349 }
3350 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
3351 if (boilerplate_value->IsUndefined()) {
3352 literals->set_the_hole(i);
3353 is_simple_acc = false;
3354 } else {
3355 literals->set(i, *boilerplate_value);
3356 }
3357 }
3358
3359 *is_simple = is_simple_acc;
3360 *depth = depth_acc;
3361}
3362
3363
Steve Blocka7e24c12009-10-30 11:49:00 +00003364Expression* Parser::ParseArrayLiteral(bool* ok) {
3365 // ArrayLiteral ::
3366 // '[' Expression? (',' Expression?)* ']'
3367
Ben Murdoch257744e2011-11-30 15:57:28 +00003368 ZoneList<Expression*>* values = new(zone()) ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003369 Expect(Token::LBRACK, CHECK_OK);
3370 while (peek() != Token::RBRACK) {
3371 Expression* elem;
3372 if (peek() == Token::COMMA) {
3373 elem = GetLiteralTheHole();
3374 } else {
3375 elem = ParseAssignmentExpression(true, CHECK_OK);
3376 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003377 values->Add(elem);
Steve Blocka7e24c12009-10-30 11:49:00 +00003378 if (peek() != Token::RBRACK) {
3379 Expect(Token::COMMA, CHECK_OK);
3380 }
3381 }
3382 Expect(Token::RBRACK, CHECK_OK);
3383
3384 // Update the scope information before the pre-parsing bailout.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003385 int literal_index = current_function_state_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003386
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003387 // Allocate a fixed array to hold all the object literals.
3388 Handle<FixedArray> object_literals =
Steve Block44f0eee2011-05-26 01:26:41 +01003389 isolate()->factory()->NewFixedArray(values->length(), TENURED);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003390 Handle<FixedDoubleArray> double_literals;
3391 ElementsKind elements_kind = FAST_SMI_ONLY_ELEMENTS;
Steve Blocka7e24c12009-10-30 11:49:00 +00003392
3393 // Fill in the literals.
3394 bool is_simple = true;
3395 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003396 for (int i = 0, n = values->length(); i < n; i++) {
3397 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
Steve Blocka7e24c12009-10-30 11:49:00 +00003398 if (m_literal != NULL && m_literal->depth() + 1 > depth) {
3399 depth = m_literal->depth() + 1;
3400 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003401 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00003402 if (boilerplate_value->IsUndefined()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003403 object_literals->set_the_hole(i);
3404 if (elements_kind == FAST_DOUBLE_ELEMENTS) {
3405 double_literals->set_the_hole(i);
3406 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003407 is_simple = false;
3408 } else {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003409 // Examine each literal element, and adjust the ElementsKind if the
3410 // literal element is not of a type that can be stored in the current
3411 // ElementsKind. Start with FAST_SMI_ONLY_ELEMENTS, and transition to
3412 // FAST_DOUBLE_ELEMENTS and FAST_ELEMENTS as necessary. Always remember
3413 // the tagged value, no matter what the ElementsKind is in case we
3414 // ultimately end up in FAST_ELEMENTS.
3415 object_literals->set(i, *boilerplate_value);
3416 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
3417 // Smi only elements. Notice if a transition to FAST_DOUBLE_ELEMENTS or
3418 // FAST_ELEMENTS is required.
3419 if (!boilerplate_value->IsSmi()) {
3420 if (boilerplate_value->IsNumber() && FLAG_smi_only_arrays) {
3421 // Allocate a double array on the FAST_DOUBLE_ELEMENTS transition to
3422 // avoid over-allocating in TENURED space.
3423 double_literals = isolate()->factory()->NewFixedDoubleArray(
3424 values->length(), TENURED);
3425 // Copy the contents of the FAST_SMI_ONLY_ELEMENT array to the
3426 // FAST_DOUBLE_ELEMENTS array so that they are in sync.
3427 for (int j = 0; j < i; ++j) {
3428 Object* smi_value = object_literals->get(j);
3429 if (smi_value->IsTheHole()) {
3430 double_literals->set_the_hole(j);
3431 } else {
3432 double_literals->set(j, Smi::cast(smi_value)->value());
3433 }
3434 }
3435 double_literals->set(i, boilerplate_value->Number());
3436 elements_kind = FAST_DOUBLE_ELEMENTS;
3437 } else {
3438 elements_kind = FAST_ELEMENTS;
3439 }
3440 }
3441 } else if (elements_kind == FAST_DOUBLE_ELEMENTS) {
3442 // Continue to store double values in to FAST_DOUBLE_ELEMENTS arrays
3443 // until the first value is seen that can't be stored as a double.
3444 if (boilerplate_value->IsNumber()) {
3445 double_literals->set(i, boilerplate_value->Number());
3446 } else {
3447 elements_kind = FAST_ELEMENTS;
3448 }
3449 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003450 }
3451 }
3452
Iain Merrick75681382010-08-19 15:07:18 +01003453 // Simple and shallow arrays can be lazily copied, we transform the
3454 // elements array to a copy-on-write array.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003455 if (is_simple && depth == 1 && values->length() > 0 &&
3456 elements_kind != FAST_DOUBLE_ELEMENTS) {
3457 object_literals->set_map(isolate()->heap()->fixed_cow_array_map());
Iain Merrick75681382010-08-19 15:07:18 +01003458 }
3459
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003460 Handle<FixedArrayBase> element_values = elements_kind == FAST_DOUBLE_ELEMENTS
3461 ? Handle<FixedArrayBase>(double_literals)
3462 : Handle<FixedArrayBase>(object_literals);
3463
3464 // Remember both the literal's constant values as well as the ElementsKind
3465 // in a 2-element FixedArray.
3466 Handle<FixedArray> literals =
3467 isolate()->factory()->NewFixedArray(2, TENURED);
3468
3469 literals->set(0, Smi::FromInt(elements_kind));
3470 literals->set(1, *element_values);
3471
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003472 return new(zone()) ArrayLiteral(
3473 isolate(), literals, values, literal_index, is_simple, depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003474}
3475
3476
3477bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
3478 return property != NULL &&
3479 property->kind() != ObjectLiteral::Property::PROTOTYPE;
3480}
3481
3482
3483bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003484 if (expression->AsLiteral() != NULL) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003485 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3486 return lit != NULL && lit->is_simple();
3487}
3488
Iain Merrick75681382010-08-19 15:07:18 +01003489
3490bool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
3491 Expression* value) {
3492 // If value is a literal the property value is already set in the
3493 // boilerplate object.
3494 if (value->AsLiteral() != NULL) return false;
3495 // If value is a materialized literal the property value is already set
3496 // in the boilerplate object if it is simple.
3497 if (CompileTimeValue::IsCompileTimeValue(value)) return false;
3498 return true;
3499}
3500
3501
Steve Blocka7e24c12009-10-30 11:49:00 +00003502Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
3503 ASSERT(IsCompileTimeValue(expression));
Steve Block44f0eee2011-05-26 01:26:41 +01003504 Handle<FixedArray> result = FACTORY->NewFixedArray(2, TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003505 ObjectLiteral* object_literal = expression->AsObjectLiteral();
3506 if (object_literal != NULL) {
3507 ASSERT(object_literal->is_simple());
Steve Block6ded16b2010-05-10 14:33:55 +01003508 if (object_literal->fast_elements()) {
3509 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3510 } else {
3511 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3512 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003513 result->set(kElementsSlot, *object_literal->constant_properties());
3514 } else {
3515 ArrayLiteral* array_literal = expression->AsArrayLiteral();
3516 ASSERT(array_literal != NULL && array_literal->is_simple());
3517 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
Leon Clarkee46be812010-01-19 14:06:41 +00003518 result->set(kElementsSlot, *array_literal->constant_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00003519 }
3520 return result;
3521}
3522
3523
3524CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
3525 Smi* type_value = Smi::cast(value->get(kTypeSlot));
3526 return static_cast<Type>(type_value->value());
3527}
3528
3529
3530Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3531 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3532}
3533
3534
3535Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
3536 if (expression->AsLiteral() != NULL) {
3537 return expression->AsLiteral()->handle();
3538 }
3539 if (CompileTimeValue::IsCompileTimeValue(expression)) {
3540 return CompileTimeValue::GetValue(expression);
3541 }
Steve Block44f0eee2011-05-26 01:26:41 +01003542 return isolate()->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003543}
3544
Steve Block1e0659c2011-05-24 12:43:12 +01003545// Defined in ast.cc
3546bool IsEqualString(void* first, void* second);
3547bool IsEqualNumber(void* first, void* second);
3548
3549
3550// Validation per 11.1.5 Object Initialiser
3551class ObjectLiteralPropertyChecker {
3552 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003553 ObjectLiteralPropertyChecker(Parser* parser, LanguageMode language_mode) :
Steve Block1e0659c2011-05-24 12:43:12 +01003554 props(&IsEqualString),
3555 elems(&IsEqualNumber),
3556 parser_(parser),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003557 language_mode_(language_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +01003558 }
3559
3560 void CheckProperty(
3561 ObjectLiteral::Property* property,
3562 Scanner::Location loc,
3563 bool* ok);
3564
3565 private:
3566 enum PropertyKind {
3567 kGetAccessor = 0x01,
3568 kSetAccessor = 0x02,
3569 kAccessor = kGetAccessor | kSetAccessor,
3570 kData = 0x04
3571 };
3572
3573 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) {
3574 switch (property->kind()) {
3575 case ObjectLiteral::Property::GETTER:
3576 return kGetAccessor;
3577 case ObjectLiteral::Property::SETTER:
3578 return kSetAccessor;
3579 default:
3580 return kData;
3581 }
3582 }
3583
3584 HashMap props;
3585 HashMap elems;
3586 Parser* parser_;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003587 LanguageMode language_mode_;
Steve Block1e0659c2011-05-24 12:43:12 +01003588};
3589
3590
3591void ObjectLiteralPropertyChecker::CheckProperty(
3592 ObjectLiteral::Property* property,
3593 Scanner::Location loc,
3594 bool* ok) {
3595
3596 ASSERT(property != NULL);
3597
3598 Literal *lit = property->key();
3599 Handle<Object> handle = lit->handle();
3600
3601 uint32_t hash;
3602 HashMap* map;
3603 void* key;
3604
3605 if (handle->IsSymbol()) {
3606 Handle<String> name(String::cast(*handle));
3607 if (name->AsArrayIndex(&hash)) {
Steve Block44f0eee2011-05-26 01:26:41 +01003608 Handle<Object> key_handle = FACTORY->NewNumberFromUint(hash);
Steve Block1e0659c2011-05-24 12:43:12 +01003609 key = key_handle.location();
3610 map = &elems;
3611 } else {
3612 key = handle.location();
3613 hash = name->Hash();
3614 map = &props;
3615 }
3616 } else if (handle->ToArrayIndex(&hash)) {
3617 key = handle.location();
3618 map = &elems;
3619 } else {
3620 ASSERT(handle->IsNumber());
3621 double num = handle->Number();
3622 char arr[100];
3623 Vector<char> buffer(arr, ARRAY_SIZE(arr));
3624 const char* str = DoubleToCString(num, buffer);
Steve Block44f0eee2011-05-26 01:26:41 +01003625 Handle<String> name = FACTORY->NewStringFromAscii(CStrVector(str));
Steve Block1e0659c2011-05-24 12:43:12 +01003626 key = name.location();
3627 hash = name->Hash();
3628 map = &props;
3629 }
3630
3631 // Lookup property previously defined, if any.
3632 HashMap::Entry* entry = map->Lookup(key, hash, true);
3633 intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
3634 intptr_t curr = GetPropertyKind(property);
3635
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003636 // Duplicate data properties are illegal in strict or extended mode.
3637 if (language_mode_ != CLASSIC_MODE && (curr & prev & kData) != 0) {
Steve Block1e0659c2011-05-24 12:43:12 +01003638 parser_->ReportMessageAt(loc, "strict_duplicate_property",
3639 Vector<const char*>::empty());
3640 *ok = false;
3641 return;
3642 }
3643 // Data property conflicting with an accessor.
3644 if (((curr & kData) && (prev & kAccessor)) ||
3645 ((prev & kData) && (curr & kAccessor))) {
3646 parser_->ReportMessageAt(loc, "accessor_data_property",
3647 Vector<const char*>::empty());
3648 *ok = false;
3649 return;
3650 }
3651 // Two accessors of the same type conflicting
3652 if ((curr & prev & kAccessor) != 0) {
3653 parser_->ReportMessageAt(loc, "accessor_get_set",
3654 Vector<const char*>::empty());
3655 *ok = false;
3656 return;
3657 }
3658
3659 // Update map
3660 entry->value = reinterpret_cast<void*> (prev | curr);
3661 *ok = true;
3662}
3663
Steve Blocka7e24c12009-10-30 11:49:00 +00003664
Leon Clarke4515c472010-02-03 11:58:03 +00003665void Parser::BuildObjectLiteralConstantProperties(
3666 ZoneList<ObjectLiteral::Property*>* properties,
3667 Handle<FixedArray> constant_properties,
3668 bool* is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003669 bool* fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003670 int* depth) {
3671 int position = 0;
3672 // Accumulate the value in local variables and store it at the end.
3673 bool is_simple_acc = true;
3674 int depth_acc = 1;
Steve Block6ded16b2010-05-10 14:33:55 +01003675 uint32_t max_element_index = 0;
3676 uint32_t elements = 0;
Leon Clarke4515c472010-02-03 11:58:03 +00003677 for (int i = 0; i < properties->length(); i++) {
3678 ObjectLiteral::Property* property = properties->at(i);
3679 if (!IsBoilerplateProperty(property)) {
3680 is_simple_acc = false;
3681 continue;
3682 }
3683 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
3684 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3685 depth_acc = m_literal->depth() + 1;
3686 }
3687
3688 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
3689 // value for COMPUTED properties, the real value is filled in at
3690 // runtime. The enumeration order is maintained.
3691 Handle<Object> key = property->key()->handle();
3692 Handle<Object> value = GetBoilerplateValue(property->value());
3693 is_simple_acc = is_simple_acc && !value->IsUndefined();
3694
Steve Block6ded16b2010-05-10 14:33:55 +01003695 // Keep track of the number of elements in the object literal and
3696 // the largest element index. If the largest element index is
3697 // much larger than the number of elements, creating an object
3698 // literal with fast elements will be a waste of space.
3699 uint32_t element_index = 0;
3700 if (key->IsString()
3701 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
3702 && element_index > max_element_index) {
3703 max_element_index = element_index;
3704 elements++;
3705 } else if (key->IsSmi()) {
3706 int key_value = Smi::cast(*key)->value();
3707 if (key_value > 0
3708 && static_cast<uint32_t>(key_value) > max_element_index) {
3709 max_element_index = key_value;
3710 }
3711 elements++;
3712 }
3713
Leon Clarke4515c472010-02-03 11:58:03 +00003714 // Add name, value pair to the fixed array.
3715 constant_properties->set(position++, *key);
3716 constant_properties->set(position++, *value);
3717 }
Steve Block6ded16b2010-05-10 14:33:55 +01003718 *fast_elements =
3719 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
Leon Clarke4515c472010-02-03 11:58:03 +00003720 *is_simple = is_simple_acc;
3721 *depth = depth_acc;
3722}
3723
3724
Ben Murdochbb769b22010-08-11 14:56:33 +01003725ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
3726 bool* ok) {
3727 // Special handling of getter and setter syntax:
3728 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3729 // We have already read the "get" or "set" keyword.
3730 Token::Value next = Next();
Steve Block9fac8402011-05-12 15:51:54 +01003731 bool is_keyword = Token::IsKeyword(next);
3732 if (next == Token::IDENTIFIER || next == Token::NUMBER ||
Steve Block1e0659c2011-05-24 12:43:12 +01003733 next == Token::FUTURE_RESERVED_WORD ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003734 next == Token::FUTURE_STRICT_RESERVED_WORD ||
Steve Block9fac8402011-05-12 15:51:54 +01003735 next == Token::STRING || is_keyword) {
3736 Handle<String> name;
3737 if (is_keyword) {
Steve Block44f0eee2011-05-26 01:26:41 +01003738 name = isolate_->factory()->LookupAsciiSymbol(Token::String(next));
Steve Block9fac8402011-05-12 15:51:54 +01003739 } else {
3740 name = GetSymbol(CHECK_OK);
3741 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003742 FunctionLiteral* value =
3743 ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01003744 false, // reserved words are allowed here
Ben Murdochbb769b22010-08-11 14:56:33 +01003745 RelocInfo::kNoPosition,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003746 FunctionLiteral::ANONYMOUS_EXPRESSION,
Ben Murdochbb769b22010-08-11 14:56:33 +01003747 CHECK_OK);
Steve Block9fac8402011-05-12 15:51:54 +01003748 // Allow any number of parameters for compatiabilty with JSC.
3749 // Specification only allows zero parameters for get and one for set.
Ben Murdochbb769b22010-08-11 14:56:33 +01003750 ObjectLiteral::Property* property =
Ben Murdoch8b112d22011-06-08 16:22:53 +01003751 new(zone()) ObjectLiteral::Property(is_getter, value);
Ben Murdochbb769b22010-08-11 14:56:33 +01003752 return property;
3753 } else {
3754 ReportUnexpectedToken(next);
3755 *ok = false;
3756 return NULL;
3757 }
3758}
3759
3760
Steve Blocka7e24c12009-10-30 11:49:00 +00003761Expression* Parser::ParseObjectLiteral(bool* ok) {
3762 // ObjectLiteral ::
3763 // '{' (
Ben Murdochbb769b22010-08-11 14:56:33 +01003764 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3765 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
Steve Blocka7e24c12009-10-30 11:49:00 +00003766 // )*[','] '}'
3767
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003768 ZoneList<ObjectLiteral::Property*>* properties =
Ben Murdoch257744e2011-11-30 15:57:28 +00003769 new(zone()) ZoneList<ObjectLiteral::Property*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003770 int number_of_boilerplate_properties = 0;
Steve Block44f0eee2011-05-26 01:26:41 +01003771 bool has_function = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003772
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003773 ObjectLiteralPropertyChecker checker(this, top_scope_->language_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01003774
Steve Blocka7e24c12009-10-30 11:49:00 +00003775 Expect(Token::LBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003776
Steve Blocka7e24c12009-10-30 11:49:00 +00003777 while (peek() != Token::RBRACE) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003778 if (fni_ != NULL) fni_->Enter();
3779
Steve Blocka7e24c12009-10-30 11:49:00 +00003780 Literal* key = NULL;
Ben Murdochbb769b22010-08-11 14:56:33 +01003781 Token::Value next = peek();
Steve Block1e0659c2011-05-24 12:43:12 +01003782
3783 // Location of the property name token
3784 Scanner::Location loc = scanner().peek_location();
3785
Ben Murdochbb769b22010-08-11 14:56:33 +01003786 switch (next) {
Steve Block1e0659c2011-05-24 12:43:12 +01003787 case Token::FUTURE_RESERVED_WORD:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003788 case Token::FUTURE_STRICT_RESERVED_WORD:
Steve Blocka7e24c12009-10-30 11:49:00 +00003789 case Token::IDENTIFIER: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003790 bool is_getter = false;
3791 bool is_setter = false;
3792 Handle<String> id =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003793 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003794 if (fni_ != NULL) fni_->PushLiteralName(id);
3795
Ben Murdochbb769b22010-08-11 14:56:33 +01003796 if ((is_getter || is_setter) && peek() != Token::COLON) {
Steve Block1e0659c2011-05-24 12:43:12 +01003797 // Update loc to point to the identifier
3798 loc = scanner().peek_location();
Steve Blocka7e24c12009-10-30 11:49:00 +00003799 ObjectLiteral::Property* property =
Ben Murdochbb769b22010-08-11 14:56:33 +01003800 ParseObjectLiteralGetSet(is_getter, CHECK_OK);
3801 if (IsBoilerplateProperty(property)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003802 number_of_boilerplate_properties++;
Ben Murdochbb769b22010-08-11 14:56:33 +01003803 }
Steve Block1e0659c2011-05-24 12:43:12 +01003804 // Validate the property.
3805 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003806 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003807 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003808
3809 if (fni_ != NULL) {
3810 fni_->Infer();
3811 fni_->Leave();
3812 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003813 continue; // restart the while
Steve Blocka7e24c12009-10-30 11:49:00 +00003814 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003815 // Failed to parse as get/set property, so it's just a property
3816 // called "get" or "set".
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003817 key = NewLiteral(id);
Steve Blocka7e24c12009-10-30 11:49:00 +00003818 break;
3819 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003820 case Token::STRING: {
3821 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003822 Handle<String> string = GetSymbol(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003823 if (fni_ != NULL) fni_->PushLiteralName(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003824 uint32_t index;
Iain Merrick75681382010-08-19 15:07:18 +01003825 if (!string.is_null() && string->AsArrayIndex(&index)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003826 key = NewNumberLiteral(index);
Ben Murdochbb769b22010-08-11 14:56:33 +01003827 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00003828 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003829 key = NewLiteral(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003830 break;
3831 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003832 case Token::NUMBER: {
3833 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003834 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01003835 double value = StringToDouble(isolate()->unicode_cache(),
3836 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01003837 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003838 key = NewNumberLiteral(value);
3839 break;
3840 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003841 default:
Ben Murdochbb769b22010-08-11 14:56:33 +01003842 if (Token::IsKeyword(next)) {
3843 Consume(next);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003844 Handle<String> string = GetSymbol(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003845 key = NewLiteral(string);
Ben Murdochbb769b22010-08-11 14:56:33 +01003846 } else {
3847 // Unexpected token.
3848 Token::Value next = Next();
3849 ReportUnexpectedToken(next);
3850 *ok = false;
3851 return NULL;
3852 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003853 }
3854
3855 Expect(Token::COLON, CHECK_OK);
3856 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
3857
3858 ObjectLiteral::Property* property =
Ben Murdoch8b112d22011-06-08 16:22:53 +01003859 new(zone()) ObjectLiteral::Property(key, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003860
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003861 // Mark top-level object literals that contain function literals and
3862 // pretenure the literal so it can be added as a constant function
3863 // property.
3864 if (top_scope_->DeclarationScope()->is_global_scope() &&
3865 value->AsFunctionLiteral() != NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +01003866 has_function = true;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003867 value->AsFunctionLiteral()->set_pretenure();
Steve Block44f0eee2011-05-26 01:26:41 +01003868 }
3869
Steve Blocka7e24c12009-10-30 11:49:00 +00003870 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3871 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
Steve Block1e0659c2011-05-24 12:43:12 +01003872 // Validate the property
3873 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003874 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003875
3876 // TODO(1240767): Consider allowing trailing comma.
3877 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003878
3879 if (fni_ != NULL) {
3880 fni_->Infer();
3881 fni_->Leave();
3882 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003883 }
3884 Expect(Token::RBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003885
Steve Blocka7e24c12009-10-30 11:49:00 +00003886 // Computation of literal_index must happen before pre parse bailout.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003887 int literal_index = current_function_state_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003888
Steve Block44f0eee2011-05-26 01:26:41 +01003889 Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray(
3890 number_of_boilerplate_properties * 2, TENURED);
Leon Clarke4515c472010-02-03 11:58:03 +00003891
Steve Blocka7e24c12009-10-30 11:49:00 +00003892 bool is_simple = true;
Steve Block6ded16b2010-05-10 14:33:55 +01003893 bool fast_elements = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003894 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003895 BuildObjectLiteralConstantProperties(properties,
Leon Clarke4515c472010-02-03 11:58:03 +00003896 constant_properties,
3897 &is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003898 &fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003899 &depth);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003900 return new(zone()) ObjectLiteral(isolate(),
3901 constant_properties,
3902 properties,
3903 literal_index,
3904 is_simple,
3905 fast_elements,
3906 depth,
3907 has_function);
Steve Blocka7e24c12009-10-30 11:49:00 +00003908}
3909
3910
3911Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003912 if (!scanner().ScanRegExpPattern(seen_equal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003913 Next();
3914 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3915 *ok = false;
3916 return NULL;
3917 }
3918
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003919 int literal_index = current_function_state_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003920
Steve Block9fac8402011-05-12 15:51:54 +01003921 Handle<String> js_pattern = NextLiteralString(TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003922 scanner().ScanRegExpFlags();
Steve Block9fac8402011-05-12 15:51:54 +01003923 Handle<String> js_flags = NextLiteralString(TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003924 Next();
3925
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003926 return new(zone()) RegExpLiteral(
3927 isolate(), js_pattern, js_flags, literal_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003928}
3929
3930
3931ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3932 // Arguments ::
3933 // '(' (AssignmentExpression)*[','] ')'
3934
Ben Murdoch257744e2011-11-30 15:57:28 +00003935 ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003936 Expect(Token::LPAREN, CHECK_OK);
3937 bool done = (peek() == Token::RPAREN);
3938 while (!done) {
3939 Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003940 result->Add(argument);
Steve Block053d10c2011-06-13 19:13:29 +01003941 if (result->length() > kMaxNumFunctionParameters) {
3942 ReportMessageAt(scanner().location(), "too_many_arguments",
3943 Vector<const char*>::empty());
3944 *ok = false;
3945 return NULL;
3946 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003947 done = (peek() == Token::RPAREN);
3948 if (!done) Expect(Token::COMMA, CHECK_OK);
3949 }
3950 Expect(Token::RPAREN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003951 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003952}
3953
3954
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003955class SingletonLogger : public ParserRecorder {
3956 public:
3957 SingletonLogger() : has_error_(false), start_(-1), end_(-1) { }
3958 ~SingletonLogger() { }
3959
3960 void Reset() { has_error_ = false; }
3961
3962 virtual void LogFunction(int start,
3963 int end,
3964 int literals,
3965 int properties,
3966 LanguageMode mode) {
3967 ASSERT(!has_error_);
3968 start_ = start;
3969 end_ = end;
3970 literals_ = literals;
3971 properties_ = properties;
3972 mode_ = mode;
3973 };
3974
3975 // Logs a symbol creation of a literal or identifier.
3976 virtual void LogAsciiSymbol(int start, Vector<const char> literal) { }
3977 virtual void LogUC16Symbol(int start, Vector<const uc16> literal) { }
3978
3979 // Logs an error message and marks the log as containing an error.
3980 // Further logging will be ignored, and ExtractData will return a vector
3981 // representing the error only.
3982 virtual void LogMessage(int start,
3983 int end,
3984 const char* message,
3985 const char* argument_opt) {
3986 has_error_ = true;
3987 start_ = start;
3988 end_ = end;
3989 message_ = message;
3990 argument_opt_ = argument_opt;
3991 }
3992
3993 virtual int function_position() { return 0; }
3994
3995 virtual int symbol_position() { return 0; }
3996
3997 virtual int symbol_ids() { return -1; }
3998
3999 virtual Vector<unsigned> ExtractData() {
4000 UNREACHABLE();
4001 return Vector<unsigned>();
4002 }
4003
4004 virtual void PauseRecording() { }
4005
4006 virtual void ResumeRecording() { }
4007
4008 bool has_error() { return has_error_; }
4009
4010 int start() { return start_; }
4011 int end() { return end_; }
4012 int literals() {
4013 ASSERT(!has_error_);
4014 return literals_;
4015 }
4016 int properties() {
4017 ASSERT(!has_error_);
4018 return properties_;
4019 }
4020 LanguageMode language_mode() {
4021 ASSERT(!has_error_);
4022 return mode_;
4023 }
4024 const char* message() {
4025 ASSERT(has_error_);
4026 return message_;
4027 }
4028 const char* argument_opt() {
4029 ASSERT(has_error_);
4030 return argument_opt_;
4031 }
4032
4033 private:
4034 bool has_error_;
4035 int start_;
4036 int end_;
4037 // For function entries.
4038 int literals_;
4039 int properties_;
4040 LanguageMode mode_;
4041 // For error messages.
4042 const char* message_;
4043 const char* argument_opt_;
4044};
4045
4046
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004047FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
4048 bool name_is_strict_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00004049 int function_token_position,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004050 FunctionLiteral::Type type,
Steve Blocka7e24c12009-10-30 11:49:00 +00004051 bool* ok) {
4052 // Function ::
4053 // '(' FormalParameterList? ')' '{' FunctionBody '}'
Steve Blocka7e24c12009-10-30 11:49:00 +00004054
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004055 // Anonymous functions were passed either the empty symbol or a null
4056 // handle as the function name. Remember if we were passed a non-empty
4057 // handle to decide whether to invoke function name inference.
4058 bool should_infer_name = function_name.is_null();
4059
4060 // We want a non-null handle as the function name.
4061 if (should_infer_name) {
4062 function_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00004063 }
4064
4065 int num_parameters = 0;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004066 // Function declarations are function scoped in normal mode, so they are
4067 // hoisted. In harmony block scoping mode they are block scoped, so they
4068 // are not hoisted.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004069 Scope* scope = (type == FunctionLiteral::DECLARATION && !is_extended_mode())
4070 ? NewScope(top_scope_->DeclarationScope(), FUNCTION_SCOPE)
4071 : NewScope(top_scope_, FUNCTION_SCOPE);
4072 ZoneList<Statement*>* body = NULL;
4073 int materialized_literal_count = -1;
4074 int expected_property_count = -1;
4075 int handler_count = 0;
Ben Murdoch8b112d22011-06-08 16:22:53 +01004076 bool only_simple_this_property_assignments;
4077 Handle<FixedArray> this_property_assignments;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004078 bool has_duplicate_parameters = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00004079 // Parse function body.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004080 { FunctionState function_state(this, scope, isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004081 top_scope_->SetScopeName(function_name);
Steve Blocka7e24c12009-10-30 11:49:00 +00004082
4083 // FormalParameterList ::
4084 // '(' (Identifier)*[','] ')'
4085 Expect(Token::LPAREN, CHECK_OK);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004086 scope->set_start_position(scanner().location().beg_pos);
Ben Murdoch257744e2011-11-30 15:57:28 +00004087 Scanner::Location name_loc = Scanner::Location::invalid();
4088 Scanner::Location dupe_loc = Scanner::Location::invalid();
4089 Scanner::Location reserved_loc = Scanner::Location::invalid();
Steve Block1e0659c2011-05-24 12:43:12 +01004090
Steve Blocka7e24c12009-10-30 11:49:00 +00004091 bool done = (peek() == Token::RPAREN);
4092 while (!done) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004093 bool is_strict_reserved = false;
Steve Block1e0659c2011-05-24 12:43:12 +01004094 Handle<String> param_name =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004095 ParseIdentifierOrStrictReservedWord(&is_strict_reserved,
4096 CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01004097
4098 // Store locations for possible future error reports.
4099 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
4100 name_loc = scanner().location();
4101 }
4102 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004103 has_duplicate_parameters = true;
Steve Block1e0659c2011-05-24 12:43:12 +01004104 dupe_loc = scanner().location();
4105 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004106 if (!reserved_loc.IsValid() && is_strict_reserved) {
Steve Block1e0659c2011-05-24 12:43:12 +01004107 reserved_loc = scanner().location();
4108 }
4109
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004110 top_scope_->DeclareParameter(param_name, is_extended_mode() ? LET : VAR);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004111 num_parameters++;
Steve Block1e0659c2011-05-24 12:43:12 +01004112 if (num_parameters > kMaxNumFunctionParameters) {
4113 ReportMessageAt(scanner().location(), "too_many_parameters",
4114 Vector<const char*>::empty());
4115 *ok = false;
4116 return NULL;
4117 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004118 done = (peek() == Token::RPAREN);
4119 if (!done) Expect(Token::COMMA, CHECK_OK);
4120 }
4121 Expect(Token::RPAREN, CHECK_OK);
4122
4123 Expect(Token::LBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00004124
4125 // If we have a named function expression, we add a local variable
4126 // declaration to the body of the function with the name of the
4127 // function and let it refer to the function itself (closure).
4128 // NOTE: We create a proxy and resolve it here so that in the
4129 // future we can change the AST to only refer to VariableProxies
4130 // instead of Variables and Proxis as is the case now.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004131 Variable* fvar = NULL;
4132 Token::Value fvar_init_op = Token::INIT_CONST;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004133 if (type == FunctionLiteral::NAMED_EXPRESSION) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004134 VariableMode fvar_mode;
4135 if (is_extended_mode()) {
4136 fvar_mode = CONST_HARMONY;
4137 fvar_init_op = Token::INIT_CONST_HARMONY;
4138 } else {
4139 fvar_mode = CONST;
4140 }
4141 fvar = top_scope_->DeclareFunctionVar(function_name, fvar_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00004142 }
4143
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004144 // Determine whether the function will be lazily compiled.
4145 // The heuristics are:
4146 // - It must not have been prohibited by the caller to Parse (some callers
4147 // need a full AST).
4148 // - The outer scope must be trivial (only global variables in scope).
4149 // - The function mustn't be a function expression with an open parenthesis
4150 // before; we consider that a hint that the function will be called
4151 // immediately, and it would be a waste of time to make it lazily
4152 // compiled.
4153 // These are all things we can know at this point, without looking at the
4154 // function itself.
Ben Murdochb8e0da22011-05-16 14:20:40 +01004155 bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
4156 top_scope_->outer_scope()->is_global_scope() &&
4157 top_scope_->HasTrivialOuterContext() &&
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004158 !parenthesized_function_);
Ben Murdochb8e0da22011-05-16 14:20:40 +01004159 parenthesized_function_ = false; // The bit was set for this function only.
Steve Blocka7e24c12009-10-30 11:49:00 +00004160
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004161 if (is_lazily_compiled) {
4162 int function_block_pos = scanner().location().beg_pos;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004163 FunctionEntry entry;
4164 if (pre_data_ != NULL) {
4165 // If we have pre_data_, we use it to skip parsing the function body.
4166 // the preparser data contains the information we need to construct the
4167 // lazy function.
4168 entry = pre_data()->GetFunctionEntry(function_block_pos);
4169 if (entry.is_valid()) {
4170 if (entry.end_pos() <= function_block_pos) {
4171 // End position greater than end of stream is safe, and hard
4172 // to check.
4173 ReportInvalidPreparseData(function_name, CHECK_OK);
4174 }
4175 scanner().SeekForward(entry.end_pos() - 1);
4176
4177 scope->set_end_position(entry.end_pos());
4178 Expect(Token::RBRACE, CHECK_OK);
4179 isolate()->counters()->total_preparse_skipped()->Increment(
4180 scope->end_position() - function_block_pos);
4181 materialized_literal_count = entry.literal_count();
4182 expected_property_count = entry.property_count();
4183 top_scope_->SetLanguageMode(entry.language_mode());
4184 only_simple_this_property_assignments = false;
4185 this_property_assignments = isolate()->factory()->empty_fixed_array();
4186 } else {
4187 is_lazily_compiled = false;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004188 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004189 } else {
4190 // With no preparser data, we partially parse the function, without
4191 // building an AST. This gathers the data needed to build a lazy
4192 // function.
4193 SingletonLogger logger;
4194 preparser::PreParser::PreParseResult result =
4195 LazyParseFunctionLiteral(&logger);
4196 if (result == preparser::PreParser::kPreParseStackOverflow) {
4197 // Propagate stack overflow.
4198 stack_overflow_ = true;
4199 *ok = false;
4200 return NULL;
4201 }
4202 if (logger.has_error()) {
4203 const char* arg = logger.argument_opt();
4204 Vector<const char*> args;
4205 if (arg != NULL) {
4206 args = Vector<const char*>(&arg, 1);
4207 }
4208 ReportMessageAt(Scanner::Location(logger.start(), logger.end()),
4209 logger.message(), args);
4210 *ok = false;
4211 return NULL;
4212 }
4213 scope->set_end_position(logger.end());
4214 Expect(Token::RBRACE, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004215 isolate()->counters()->total_preparse_skipped()->Increment(
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004216 scope->end_position() - function_block_pos);
4217 materialized_literal_count = logger.literals();
4218 expected_property_count = logger.properties();
4219 top_scope_->SetLanguageMode(logger.language_mode());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004220 only_simple_this_property_assignments = false;
4221 this_property_assignments = isolate()->factory()->empty_fixed_array();
Leon Clarkeac952652010-07-15 11:15:24 +01004222 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004223 }
4224
4225 if (!is_lazily_compiled) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004226 body = new(zone()) ZoneList<Statement*>(8);
4227 if (fvar != NULL) {
4228 VariableProxy* fproxy = top_scope_->NewUnresolved(function_name);
4229 fproxy->BindTo(fvar);
4230 body->Add(new(zone()) ExpressionStatement(
4231 new(zone()) Assignment(isolate(),
4232 fvar_init_op,
4233 fproxy,
4234 new(zone()) ThisFunction(isolate()),
4235 RelocInfo::kNoPosition)));
4236 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004237 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
4238
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004239 materialized_literal_count = function_state.materialized_literal_count();
4240 expected_property_count = function_state.expected_property_count();
4241 handler_count = function_state.handler_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00004242 only_simple_this_property_assignments =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004243 function_state.only_simple_this_property_assignments();
4244 this_property_assignments = function_state.this_property_assignments();
Steve Blocka7e24c12009-10-30 11:49:00 +00004245
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004246 Expect(Token::RBRACE, CHECK_OK);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004247 scope->set_end_position(scanner().location().end_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00004248 }
4249
Steve Block1e0659c2011-05-24 12:43:12 +01004250 // Validate strict mode.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004251 if (!top_scope_->is_classic_mode()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004252 if (IsEvalOrArguments(function_name)) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004253 int start_pos = scope->start_position();
Steve Block1e0659c2011-05-24 12:43:12 +01004254 int position = function_token_position != RelocInfo::kNoPosition
4255 ? function_token_position
4256 : (start_pos > 0 ? start_pos - 1 : start_pos);
4257 Scanner::Location location = Scanner::Location(position, start_pos);
4258 ReportMessageAt(location,
4259 "strict_function_name", Vector<const char*>::empty());
4260 *ok = false;
4261 return NULL;
4262 }
4263 if (name_loc.IsValid()) {
4264 ReportMessageAt(name_loc, "strict_param_name",
4265 Vector<const char*>::empty());
4266 *ok = false;
4267 return NULL;
4268 }
4269 if (dupe_loc.IsValid()) {
4270 ReportMessageAt(dupe_loc, "strict_param_dupe",
4271 Vector<const char*>::empty());
4272 *ok = false;
4273 return NULL;
4274 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004275 if (name_is_strict_reserved) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004276 int start_pos = scope->start_position();
Steve Block1e0659c2011-05-24 12:43:12 +01004277 int position = function_token_position != RelocInfo::kNoPosition
4278 ? function_token_position
4279 : (start_pos > 0 ? start_pos - 1 : start_pos);
4280 Scanner::Location location = Scanner::Location(position, start_pos);
4281 ReportMessageAt(location, "strict_reserved_word",
4282 Vector<const char*>::empty());
4283 *ok = false;
4284 return NULL;
4285 }
4286 if (reserved_loc.IsValid()) {
4287 ReportMessageAt(reserved_loc, "strict_reserved_word",
4288 Vector<const char*>::empty());
4289 *ok = false;
4290 return NULL;
4291 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004292 CheckOctalLiteral(scope->start_position(),
4293 scope->end_position(),
4294 CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01004295 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004296 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01004297
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004298 if (is_extended_mode()) {
Ben Murdoch589d6972011-11-30 16:04:58 +00004299 CheckConflictingVarDeclarations(scope, CHECK_OK);
4300 }
4301
Ben Murdoch8b112d22011-06-08 16:22:53 +01004302 FunctionLiteral* function_literal =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004303 new(zone()) FunctionLiteral(isolate(),
4304 function_name,
Ben Murdoch8b112d22011-06-08 16:22:53 +01004305 scope,
4306 body,
4307 materialized_literal_count,
4308 expected_property_count,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004309 handler_count,
Ben Murdoch8b112d22011-06-08 16:22:53 +01004310 only_simple_this_property_assignments,
4311 this_property_assignments,
4312 num_parameters,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004313 type,
4314 has_duplicate_parameters);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004315 function_literal->set_function_token_position(function_token_position);
4316
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004317 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004318 return function_literal;
Steve Blocka7e24c12009-10-30 11:49:00 +00004319}
4320
4321
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004322preparser::PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
4323 SingletonLogger* logger) {
4324 HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse());
4325 ASSERT_EQ(Token::LBRACE, scanner().current_token());
4326
4327 if (reusable_preparser_ == NULL) {
4328 intptr_t stack_limit = isolate()->stack_guard()->real_climit();
4329 bool do_allow_lazy = true;
4330 reusable_preparser_ = new preparser::PreParser(&scanner_,
4331 NULL,
4332 stack_limit,
4333 do_allow_lazy,
4334 allow_natives_syntax_);
4335 }
4336 preparser::PreParser::PreParseResult result =
4337 reusable_preparser_->PreParseLazyFunction(top_scope_->language_mode(),
4338 logger);
4339 return result;
4340}
4341
4342
Steve Blocka7e24c12009-10-30 11:49:00 +00004343Expression* Parser::ParseV8Intrinsic(bool* ok) {
4344 // CallRuntime ::
4345 // '%' Identifier Arguments
4346
4347 Expect(Token::MOD, CHECK_OK);
4348 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00004349 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004350
4351 if (extension_ != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004352 // The extension structures are only accessible while parsing the
4353 // very first time not when reparsing because of lazy compilation.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004354 top_scope_->DeclarationScope()->ForceEagerCompilation();
Steve Blocka7e24c12009-10-30 11:49:00 +00004355 }
4356
Steve Block44f0eee2011-05-26 01:26:41 +01004357 const Runtime::Function* function = Runtime::FunctionForSymbol(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00004358
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004359 // Check for built-in IS_VAR macro.
4360 if (function != NULL &&
4361 function->intrinsic_type == Runtime::RUNTIME &&
4362 function->function_id == Runtime::kIS_VAR) {
4363 // %IS_VAR(x) evaluates to x if x is a variable,
4364 // leads to a parse error otherwise. Could be implemented as an
4365 // inline function %_IS_VAR(x) to eliminate this special case.
4366 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
4367 return args->at(0);
4368 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00004369 ReportMessage("unable_to_parse", Vector<const char*>::empty());
Steve Block6ded16b2010-05-10 14:33:55 +01004370 *ok = false;
4371 return NULL;
Steve Block6ded16b2010-05-10 14:33:55 +01004372 }
4373 }
4374
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004375 // Check that the expected number of arguments are being passed.
4376 if (function != NULL &&
4377 function->nargs != -1 &&
4378 function->nargs != args->length()) {
4379 ReportMessage("illegal_access", Vector<const char*>::empty());
4380 *ok = false;
4381 return NULL;
4382 }
4383
4384 // We have a valid intrinsics call or a call to a builtin.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004385 return new(zone()) CallRuntime(isolate(), name, function, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00004386}
4387
4388
Steve Block1e0659c2011-05-24 12:43:12 +01004389bool Parser::peek_any_identifier() {
4390 Token::Value next = peek();
4391 return next == Token::IDENTIFIER ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004392 next == Token::FUTURE_RESERVED_WORD ||
4393 next == Token::FUTURE_STRICT_RESERVED_WORD;
Steve Block1e0659c2011-05-24 12:43:12 +01004394}
4395
4396
Steve Blocka7e24c12009-10-30 11:49:00 +00004397void Parser::Consume(Token::Value token) {
4398 Token::Value next = Next();
4399 USE(next);
4400 USE(token);
4401 ASSERT(next == token);
4402}
4403
4404
4405void Parser::Expect(Token::Value token, bool* ok) {
4406 Token::Value next = Next();
4407 if (next == token) return;
4408 ReportUnexpectedToken(next);
4409 *ok = false;
4410}
4411
4412
Leon Clarke4515c472010-02-03 11:58:03 +00004413bool Parser::Check(Token::Value token) {
4414 Token::Value next = peek();
4415 if (next == token) {
4416 Consume(next);
4417 return true;
4418 }
4419 return false;
4420}
4421
4422
Steve Blocka7e24c12009-10-30 11:49:00 +00004423void Parser::ExpectSemicolon(bool* ok) {
4424 // Check for automatic semicolon insertion according to
4425 // the rules given in ECMA-262, section 7.9, page 21.
4426 Token::Value tok = peek();
4427 if (tok == Token::SEMICOLON) {
4428 Next();
4429 return;
4430 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004431 if (scanner().HasAnyLineTerminatorBeforeNext() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00004432 tok == Token::RBRACE ||
4433 tok == Token::EOS) {
4434 return;
4435 }
4436 Expect(Token::SEMICOLON, ok);
4437}
4438
4439
4440Literal* Parser::GetLiteralUndefined() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004441 return NewLiteral(isolate()->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00004442}
4443
4444
4445Literal* Parser::GetLiteralTheHole() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004446 return NewLiteral(isolate()->factory()->the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00004447}
4448
4449
4450Literal* Parser::GetLiteralNumber(double value) {
4451 return NewNumberLiteral(value);
4452}
4453
4454
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004455// Parses an identifier that is valid for the current scope, in particular it
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004456// fails on strict mode future reserved keywords in a strict scope.
Steve Blocka7e24c12009-10-30 11:49:00 +00004457Handle<String> Parser::ParseIdentifier(bool* ok) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004458 if (!top_scope_->is_classic_mode()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004459 Expect(Token::IDENTIFIER, ok);
4460 } else if (!Check(Token::IDENTIFIER)) {
4461 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
4462 }
4463 if (!*ok) return Handle<String>();
4464 return GetSymbol(ok);
Steve Block1e0659c2011-05-24 12:43:12 +01004465}
4466
4467
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004468// Parses and identifier or a strict mode future reserved word, and indicate
4469// whether it is strict mode future reserved.
4470Handle<String> Parser::ParseIdentifierOrStrictReservedWord(
4471 bool* is_strict_reserved, bool* ok) {
4472 *is_strict_reserved = false;
4473 if (!Check(Token::IDENTIFIER)) {
4474 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
4475 *is_strict_reserved = true;
Steve Block1e0659c2011-05-24 12:43:12 +01004476 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004477 if (!*ok) return Handle<String>();
Iain Merrick9ac36c92010-09-13 15:29:50 +01004478 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00004479}
4480
Ben Murdochbb769b22010-08-11 14:56:33 +01004481
4482Handle<String> Parser::ParseIdentifierName(bool* ok) {
4483 Token::Value next = Next();
Steve Block1e0659c2011-05-24 12:43:12 +01004484 if (next != Token::IDENTIFIER &&
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004485 next != Token::FUTURE_RESERVED_WORD &&
4486 next != Token::FUTURE_STRICT_RESERVED_WORD &&
4487 !Token::IsKeyword(next)) {
Ben Murdochbb769b22010-08-11 14:56:33 +01004488 ReportUnexpectedToken(next);
4489 *ok = false;
4490 return Handle<String>();
4491 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01004492 return GetSymbol(ok);
Ben Murdochbb769b22010-08-11 14:56:33 +01004493}
4494
4495
Steve Block1e0659c2011-05-24 12:43:12 +01004496// Checks LHS expression for assignment and prefix/postfix increment/decrement
4497// in strict mode.
4498void Parser::CheckStrictModeLValue(Expression* expression,
4499 const char* error,
4500 bool* ok) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004501 ASSERT(!top_scope_->is_classic_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01004502 VariableProxy* lhs = expression != NULL
4503 ? expression->AsVariableProxy()
4504 : NULL;
4505
4506 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
4507 ReportMessage(error, Vector<const char*>::empty());
4508 *ok = false;
4509 }
4510}
4511
4512
Ben Murdoch257744e2011-11-30 15:57:28 +00004513// Checks whether an octal literal was last seen between beg_pos and end_pos.
4514// If so, reports an error. Only called for strict mode.
Steve Block1e0659c2011-05-24 12:43:12 +01004515void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
Ben Murdoch257744e2011-11-30 15:57:28 +00004516 Scanner::Location octal = scanner().octal_position();
4517 if (octal.IsValid() &&
4518 beg_pos <= octal.beg_pos &&
4519 octal.end_pos <= end_pos) {
4520 ReportMessageAt(octal, "strict_octal_literal",
Steve Block1e0659c2011-05-24 12:43:12 +01004521 Vector<const char*>::empty());
4522 scanner().clear_octal_position();
4523 *ok = false;
4524 }
4525}
4526
4527
Ben Murdoch589d6972011-11-30 16:04:58 +00004528void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
4529 Declaration* decl = scope->CheckConflictingVarDeclarations();
4530 if (decl != NULL) {
4531 // In harmony mode we treat conflicting variable bindinds as early
4532 // errors. See ES5 16 for a definition of early errors.
4533 Handle<String> name = decl->proxy()->name();
4534 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
4535 const char* elms[2] = { "Variable", *c_string };
4536 Vector<const char*> args(elms, 2);
4537 int position = decl->proxy()->position();
4538 Scanner::Location location = position == RelocInfo::kNoPosition
4539 ? Scanner::Location::invalid()
4540 : Scanner::Location(position, position + 1);
4541 ReportMessageAt(location, "redeclaration", args);
4542 *ok = false;
4543 }
4544}
4545
4546
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004547// This function reads an identifier name and determines whether or not it
Steve Block1e0659c2011-05-24 12:43:12 +01004548// is 'get' or 'set'.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004549Handle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get,
4550 bool* is_set,
4551 bool* ok) {
4552 Handle<String> result = ParseIdentifierName(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00004553 if (!*ok) return Handle<String>();
Steve Block9fac8402011-05-12 15:51:54 +01004554 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
4555 const char* token = scanner().literal_ascii_string().start();
4556 *is_get = strncmp(token, "get", 3) == 0;
4557 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00004558 }
Steve Block1e0659c2011-05-24 12:43:12 +01004559 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00004560}
4561
4562
4563// ----------------------------------------------------------------------------
4564// Parser support
4565
4566
4567bool Parser::TargetStackContainsLabel(Handle<String> label) {
4568 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4569 BreakableStatement* stat = t->node()->AsBreakableStatement();
4570 if (stat != NULL && ContainsLabel(stat->labels(), label))
4571 return true;
4572 }
4573 return false;
4574}
4575
4576
4577BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
4578 bool anonymous = label.is_null();
4579 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4580 BreakableStatement* stat = t->node()->AsBreakableStatement();
4581 if (stat == NULL) continue;
4582 if ((anonymous && stat->is_target_for_anonymous()) ||
4583 (!anonymous && ContainsLabel(stat->labels(), label))) {
4584 RegisterTargetUse(stat->break_target(), t->previous());
4585 return stat;
4586 }
4587 }
4588 return NULL;
4589}
4590
4591
4592IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
4593 bool* ok) {
4594 bool anonymous = label.is_null();
4595 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4596 IterationStatement* stat = t->node()->AsIterationStatement();
4597 if (stat == NULL) continue;
4598
4599 ASSERT(stat->is_target_for_anonymous());
4600 if (anonymous || ContainsLabel(stat->labels(), label)) {
4601 RegisterTargetUse(stat->continue_target(), t->previous());
4602 return stat;
4603 }
4604 }
4605 return NULL;
4606}
4607
4608
Ben Murdoch8b112d22011-06-08 16:22:53 +01004609void Parser::RegisterTargetUse(Label* target, Target* stop) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004610 // Register that a break target found at the given stop in the
4611 // target stack has been used from the top of the target stack. Add
4612 // the break target to any TargetCollectors passed on the stack.
4613 for (Target* t = target_stack_; t != stop; t = t->previous()) {
4614 TargetCollector* collector = t->node()->AsTargetCollector();
4615 if (collector != NULL) collector->AddTarget(target);
4616 }
4617}
4618
4619
4620Literal* Parser::NewNumberLiteral(double number) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004621 return NewLiteral(isolate()->factory()->NewNumber(number, TENURED));
Steve Blocka7e24c12009-10-30 11:49:00 +00004622}
4623
4624
4625Expression* Parser::NewThrowReferenceError(Handle<String> type) {
Steve Block44f0eee2011-05-26 01:26:41 +01004626 return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00004627 type, HandleVector<Object>(NULL, 0));
4628}
4629
4630
4631Expression* Parser::NewThrowSyntaxError(Handle<String> type,
4632 Handle<Object> first) {
4633 int argc = first.is_null() ? 0 : 1;
4634 Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
Steve Block44f0eee2011-05-26 01:26:41 +01004635 return NewThrowError(
4636 isolate()->factory()->MakeSyntaxError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00004637}
4638
4639
4640Expression* Parser::NewThrowTypeError(Handle<String> type,
4641 Handle<Object> first,
4642 Handle<Object> second) {
4643 ASSERT(!first.is_null() && !second.is_null());
4644 Handle<Object> elements[] = { first, second };
4645 Vector< Handle<Object> > arguments =
4646 HandleVector<Object>(elements, ARRAY_SIZE(elements));
Steve Block44f0eee2011-05-26 01:26:41 +01004647 return NewThrowError(
4648 isolate()->factory()->MakeTypeError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00004649}
4650
4651
4652Expression* Parser::NewThrowError(Handle<String> constructor,
4653 Handle<String> type,
4654 Vector< Handle<Object> > arguments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004655 int argc = arguments.length();
Steve Block44f0eee2011-05-26 01:26:41 +01004656 Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc,
4657 TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004658 for (int i = 0; i < argc; i++) {
4659 Handle<Object> element = arguments[i];
4660 if (!element.is_null()) {
Steve Block1e0659c2011-05-24 12:43:12 +01004661 elements->set(i, *element);
Steve Blocka7e24c12009-10-30 11:49:00 +00004662 }
4663 }
Steve Block44f0eee2011-05-26 01:26:41 +01004664 Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(elements,
4665 TENURED);
Steve Block1e0659c2011-05-24 12:43:12 +01004666
Ben Murdoch257744e2011-11-30 15:57:28 +00004667 ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004668 args->Add(NewLiteral(type));
4669 args->Add(NewLiteral(array));
4670 CallRuntime* call_constructor = new(zone()) CallRuntime(isolate(),
4671 constructor,
4672 NULL,
4673 args);
4674 return new(zone()) Throw(isolate(),
4675 call_constructor,
4676 scanner().location().beg_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00004677}
4678
Leon Clarke4515c472010-02-03 11:58:03 +00004679// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +00004680// Regular expressions
4681
4682
4683RegExpParser::RegExpParser(FlatStringReader* in,
4684 Handle<String>* error,
4685 bool multiline)
Steve Block44f0eee2011-05-26 01:26:41 +01004686 : isolate_(Isolate::Current()),
4687 error_(error),
4688 captures_(NULL),
4689 in_(in),
4690 current_(kEndMarker),
4691 next_pos_(0),
4692 capture_count_(0),
4693 has_more_(true),
4694 multiline_(multiline),
4695 simple_(false),
4696 contains_anchor_(false),
4697 is_scanned_for_captures_(false),
4698 failed_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004699 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004700}
4701
4702
4703uc32 RegExpParser::Next() {
4704 if (has_next()) {
4705 return in()->Get(next_pos_);
4706 } else {
4707 return kEndMarker;
4708 }
4709}
4710
4711
4712void RegExpParser::Advance() {
4713 if (next_pos_ < in()->length()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004714 StackLimitCheck check(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004715 if (check.HasOverflowed()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004716 ReportError(CStrVector(Isolate::kStackOverflowMessage));
4717 } else if (isolate()->zone()->excess_allocation()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004718 ReportError(CStrVector("Regular expression too large"));
4719 } else {
4720 current_ = in()->Get(next_pos_);
4721 next_pos_++;
4722 }
4723 } else {
4724 current_ = kEndMarker;
4725 has_more_ = false;
4726 }
4727}
4728
4729
4730void RegExpParser::Reset(int pos) {
4731 next_pos_ = pos;
4732 Advance();
4733}
4734
4735
4736void RegExpParser::Advance(int dist) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004737 next_pos_ += dist - 1;
4738 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004739}
4740
4741
4742bool RegExpParser::simple() {
4743 return simple_;
4744}
4745
4746RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
4747 failed_ = true;
Steve Block44f0eee2011-05-26 01:26:41 +01004748 *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004749 // Zip to the end to make sure the no more input is read.
4750 current_ = kEndMarker;
4751 next_pos_ = in()->length();
4752 return NULL;
4753}
4754
4755
4756// Pattern ::
4757// Disjunction
4758RegExpTree* RegExpParser::ParsePattern() {
4759 RegExpTree* result = ParseDisjunction(CHECK_FAILED);
4760 ASSERT(!has_more());
4761 // If the result of parsing is a literal string atom, and it has the
4762 // same length as the input, then the atom is identical to the input.
4763 if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
4764 simple_ = true;
4765 }
4766 return result;
4767}
4768
4769
4770// Disjunction ::
4771// Alternative
4772// Alternative | Disjunction
4773// Alternative ::
4774// [empty]
4775// Term Alternative
4776// Term ::
4777// Assertion
4778// Atom
4779// Atom Quantifier
4780RegExpTree* RegExpParser::ParseDisjunction() {
4781 // Used to store current state while parsing subexpressions.
4782 RegExpParserState initial_state(NULL, INITIAL, 0);
4783 RegExpParserState* stored_state = &initial_state;
4784 // Cache the builder in a local variable for quick access.
4785 RegExpBuilder* builder = initial_state.builder();
4786 while (true) {
4787 switch (current()) {
4788 case kEndMarker:
4789 if (stored_state->IsSubexpression()) {
4790 // Inside a parenthesized group when hitting end of input.
4791 ReportError(CStrVector("Unterminated group") CHECK_FAILED);
4792 }
4793 ASSERT_EQ(INITIAL, stored_state->group_type());
4794 // Parsing completed successfully.
4795 return builder->ToRegExp();
4796 case ')': {
4797 if (!stored_state->IsSubexpression()) {
4798 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
4799 }
4800 ASSERT_NE(INITIAL, stored_state->group_type());
4801
4802 Advance();
4803 // End disjunction parsing and convert builder content to new single
4804 // regexp atom.
4805 RegExpTree* body = builder->ToRegExp();
4806
4807 int end_capture_index = captures_started();
4808
4809 int capture_index = stored_state->capture_index();
4810 SubexpressionType type = stored_state->group_type();
4811
4812 // Restore previous state.
4813 stored_state = stored_state->previous_state();
4814 builder = stored_state->builder();
4815
4816 // Build result of subexpression.
4817 if (type == CAPTURE) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01004818 RegExpCapture* capture = new(zone()) RegExpCapture(body, capture_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00004819 captures_->at(capture_index - 1) = capture;
4820 body = capture;
4821 } else if (type != GROUPING) {
4822 ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
4823 bool is_positive = (type == POSITIVE_LOOKAHEAD);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004824 body = new(zone()) RegExpLookahead(body,
Steve Blocka7e24c12009-10-30 11:49:00 +00004825 is_positive,
4826 end_capture_index - capture_index,
4827 capture_index);
4828 }
4829 builder->AddAtom(body);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004830 // For compatability with JSC and ES3, we allow quantifiers after
4831 // lookaheads, and break in all cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00004832 break;
4833 }
4834 case '|': {
4835 Advance();
4836 builder->NewAlternative();
4837 continue;
4838 }
4839 case '*':
4840 case '+':
4841 case '?':
4842 return ReportError(CStrVector("Nothing to repeat"));
4843 case '^': {
4844 Advance();
4845 if (multiline_) {
4846 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004847 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE));
Steve Blocka7e24c12009-10-30 11:49:00 +00004848 } else {
4849 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004850 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT));
Steve Blocka7e24c12009-10-30 11:49:00 +00004851 set_contains_anchor();
4852 }
4853 continue;
4854 }
4855 case '$': {
4856 Advance();
4857 RegExpAssertion::Type type =
4858 multiline_ ? RegExpAssertion::END_OF_LINE :
4859 RegExpAssertion::END_OF_INPUT;
Ben Murdoch8b112d22011-06-08 16:22:53 +01004860 builder->AddAssertion(new(zone()) RegExpAssertion(type));
Steve Blocka7e24c12009-10-30 11:49:00 +00004861 continue;
4862 }
4863 case '.': {
4864 Advance();
4865 // everything except \x0a, \x0d, \u2028 and \u2029
Ben Murdoch257744e2011-11-30 15:57:28 +00004866 ZoneList<CharacterRange>* ranges =
4867 new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004868 CharacterRange::AddClassEscape('.', ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004869 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004870 builder->AddAtom(atom);
4871 break;
4872 }
4873 case '(': {
4874 SubexpressionType type = CAPTURE;
4875 Advance();
4876 if (current() == '?') {
4877 switch (Next()) {
4878 case ':':
4879 type = GROUPING;
4880 break;
4881 case '=':
4882 type = POSITIVE_LOOKAHEAD;
4883 break;
4884 case '!':
4885 type = NEGATIVE_LOOKAHEAD;
4886 break;
4887 default:
4888 ReportError(CStrVector("Invalid group") CHECK_FAILED);
4889 break;
4890 }
4891 Advance(2);
4892 } else {
4893 if (captures_ == NULL) {
Ben Murdoch257744e2011-11-30 15:57:28 +00004894 captures_ = new(zone()) ZoneList<RegExpCapture*>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004895 }
4896 if (captures_started() >= kMaxCaptures) {
4897 ReportError(CStrVector("Too many captures") CHECK_FAILED);
4898 }
4899 captures_->Add(NULL);
4900 }
4901 // Store current state and begin new disjunction parsing.
Ben Murdoch8b112d22011-06-08 16:22:53 +01004902 stored_state = new(zone()) RegExpParserState(stored_state,
Steve Blocka7e24c12009-10-30 11:49:00 +00004903 type,
4904 captures_started());
4905 builder = stored_state->builder();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004906 continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00004907 }
4908 case '[': {
4909 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
4910 builder->AddAtom(atom);
4911 break;
4912 }
4913 // Atom ::
4914 // \ AtomEscape
4915 case '\\':
4916 switch (Next()) {
4917 case kEndMarker:
4918 return ReportError(CStrVector("\\ at end of pattern"));
4919 case 'b':
4920 Advance(2);
4921 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004922 new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004923 continue;
4924 case 'B':
4925 Advance(2);
4926 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004927 new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004928 continue;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004929 // AtomEscape ::
4930 // CharacterClassEscape
4931 //
4932 // CharacterClassEscape :: one of
4933 // d D s S w W
Steve Blocka7e24c12009-10-30 11:49:00 +00004934 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
4935 uc32 c = Next();
4936 Advance(2);
Ben Murdoch257744e2011-11-30 15:57:28 +00004937 ZoneList<CharacterRange>* ranges =
4938 new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004939 CharacterRange::AddClassEscape(c, ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004940 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004941 builder->AddAtom(atom);
4942 break;
4943 }
4944 case '1': case '2': case '3': case '4': case '5': case '6':
4945 case '7': case '8': case '9': {
4946 int index = 0;
4947 if (ParseBackReferenceIndex(&index)) {
4948 RegExpCapture* capture = NULL;
4949 if (captures_ != NULL && index <= captures_->length()) {
4950 capture = captures_->at(index - 1);
4951 }
4952 if (capture == NULL) {
4953 builder->AddEmpty();
4954 break;
4955 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01004956 RegExpTree* atom = new(zone()) RegExpBackReference(capture);
Steve Blocka7e24c12009-10-30 11:49:00 +00004957 builder->AddAtom(atom);
4958 break;
4959 }
4960 uc32 first_digit = Next();
4961 if (first_digit == '8' || first_digit == '9') {
4962 // Treat as identity escape
4963 builder->AddCharacter(first_digit);
4964 Advance(2);
4965 break;
4966 }
4967 }
4968 // FALLTHROUGH
4969 case '0': {
4970 Advance();
4971 uc32 octal = ParseOctalLiteral();
4972 builder->AddCharacter(octal);
4973 break;
4974 }
4975 // ControlEscape :: one of
4976 // f n r t v
4977 case 'f':
4978 Advance(2);
4979 builder->AddCharacter('\f');
4980 break;
4981 case 'n':
4982 Advance(2);
4983 builder->AddCharacter('\n');
4984 break;
4985 case 'r':
4986 Advance(2);
4987 builder->AddCharacter('\r');
4988 break;
4989 case 't':
4990 Advance(2);
4991 builder->AddCharacter('\t');
4992 break;
4993 case 'v':
4994 Advance(2);
4995 builder->AddCharacter('\v');
4996 break;
4997 case 'c': {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004998 Advance();
4999 uc32 controlLetter = Next();
5000 // Special case if it is an ASCII letter.
5001 // Convert lower case letters to uppercase.
5002 uc32 letter = controlLetter & ~('a' ^ 'A');
5003 if (letter < 'A' || 'Z' < letter) {
5004 // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
5005 // This is outside the specification. We match JSC in
5006 // reading the backslash as a literal character instead
5007 // of as starting an escape.
5008 builder->AddCharacter('\\');
5009 } else {
5010 Advance(2);
5011 builder->AddCharacter(controlLetter & 0x1f);
5012 }
Steve Blocka7e24c12009-10-30 11:49:00 +00005013 break;
5014 }
5015 case 'x': {
5016 Advance(2);
5017 uc32 value;
5018 if (ParseHexEscape(2, &value)) {
5019 builder->AddCharacter(value);
5020 } else {
5021 builder->AddCharacter('x');
5022 }
5023 break;
5024 }
5025 case 'u': {
5026 Advance(2);
5027 uc32 value;
5028 if (ParseHexEscape(4, &value)) {
5029 builder->AddCharacter(value);
5030 } else {
5031 builder->AddCharacter('u');
5032 }
5033 break;
5034 }
5035 default:
5036 // Identity escape.
5037 builder->AddCharacter(Next());
5038 Advance(2);
5039 break;
5040 }
5041 break;
5042 case '{': {
5043 int dummy;
5044 if (ParseIntervalQuantifier(&dummy, &dummy)) {
5045 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
5046 }
5047 // fallthrough
5048 }
5049 default:
5050 builder->AddCharacter(current());
5051 Advance();
5052 break;
5053 } // end switch(current())
5054
5055 int min;
5056 int max;
5057 switch (current()) {
5058 // QuantifierPrefix ::
5059 // *
5060 // +
5061 // ?
5062 // {
5063 case '*':
5064 min = 0;
5065 max = RegExpTree::kInfinity;
5066 Advance();
5067 break;
5068 case '+':
5069 min = 1;
5070 max = RegExpTree::kInfinity;
5071 Advance();
5072 break;
5073 case '?':
5074 min = 0;
5075 max = 1;
5076 Advance();
5077 break;
5078 case '{':
5079 if (ParseIntervalQuantifier(&min, &max)) {
5080 if (max < min) {
5081 ReportError(CStrVector("numbers out of order in {} quantifier.")
5082 CHECK_FAILED);
5083 }
5084 break;
5085 } else {
5086 continue;
5087 }
5088 default:
5089 continue;
5090 }
Leon Clarkee46be812010-01-19 14:06:41 +00005091 RegExpQuantifier::Type type = RegExpQuantifier::GREEDY;
Steve Blocka7e24c12009-10-30 11:49:00 +00005092 if (current() == '?') {
Leon Clarkee46be812010-01-19 14:06:41 +00005093 type = RegExpQuantifier::NON_GREEDY;
5094 Advance();
5095 } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
5096 // FLAG_regexp_possessive_quantifier is a debug-only flag.
5097 type = RegExpQuantifier::POSSESSIVE;
Steve Blocka7e24c12009-10-30 11:49:00 +00005098 Advance();
5099 }
Leon Clarkee46be812010-01-19 14:06:41 +00005100 builder->AddQuantifierToAtom(min, max, type);
Steve Blocka7e24c12009-10-30 11:49:00 +00005101 }
5102}
5103
Steve Blocka7e24c12009-10-30 11:49:00 +00005104
5105#ifdef DEBUG
5106// Currently only used in an ASSERT.
5107static bool IsSpecialClassEscape(uc32 c) {
5108 switch (c) {
5109 case 'd': case 'D':
5110 case 's': case 'S':
5111 case 'w': case 'W':
5112 return true;
5113 default:
5114 return false;
5115 }
5116}
5117#endif
5118
5119
5120// In order to know whether an escape is a backreference or not we have to scan
5121// the entire regexp and find the number of capturing parentheses. However we
5122// don't want to scan the regexp twice unless it is necessary. This mini-parser
5123// is called when needed. It can see the difference between capturing and
5124// noncapturing parentheses and can skip character classes and backslash-escaped
5125// characters.
5126void RegExpParser::ScanForCaptures() {
5127 // Start with captures started previous to current position
5128 int capture_count = captures_started();
5129 // Add count of captures after this position.
5130 int n;
5131 while ((n = current()) != kEndMarker) {
5132 Advance();
5133 switch (n) {
5134 case '\\':
5135 Advance();
5136 break;
5137 case '[': {
5138 int c;
5139 while ((c = current()) != kEndMarker) {
5140 Advance();
5141 if (c == '\\') {
5142 Advance();
5143 } else {
5144 if (c == ']') break;
5145 }
5146 }
5147 break;
5148 }
5149 case '(':
5150 if (current() != '?') capture_count++;
5151 break;
5152 }
5153 }
5154 capture_count_ = capture_count;
5155 is_scanned_for_captures_ = true;
5156}
5157
5158
5159bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
5160 ASSERT_EQ('\\', current());
5161 ASSERT('1' <= Next() && Next() <= '9');
5162 // Try to parse a decimal literal that is no greater than the total number
5163 // of left capturing parentheses in the input.
5164 int start = position();
5165 int value = Next() - '0';
5166 Advance(2);
5167 while (true) {
5168 uc32 c = current();
5169 if (IsDecimalDigit(c)) {
5170 value = 10 * value + (c - '0');
5171 if (value > kMaxCaptures) {
5172 Reset(start);
5173 return false;
5174 }
5175 Advance();
5176 } else {
5177 break;
5178 }
5179 }
5180 if (value > captures_started()) {
5181 if (!is_scanned_for_captures_) {
5182 int saved_position = position();
5183 ScanForCaptures();
5184 Reset(saved_position);
5185 }
5186 if (value > capture_count_) {
5187 Reset(start);
5188 return false;
5189 }
5190 }
5191 *index_out = value;
5192 return true;
5193}
5194
5195
5196// QuantifierPrefix ::
5197// { DecimalDigits }
5198// { DecimalDigits , }
5199// { DecimalDigits , DecimalDigits }
5200//
5201// Returns true if parsing succeeds, and set the min_out and max_out
5202// values. Values are truncated to RegExpTree::kInfinity if they overflow.
5203bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
5204 ASSERT_EQ(current(), '{');
5205 int start = position();
5206 Advance();
5207 int min = 0;
5208 if (!IsDecimalDigit(current())) {
5209 Reset(start);
5210 return false;
5211 }
5212 while (IsDecimalDigit(current())) {
5213 int next = current() - '0';
5214 if (min > (RegExpTree::kInfinity - next) / 10) {
5215 // Overflow. Skip past remaining decimal digits and return -1.
5216 do {
5217 Advance();
5218 } while (IsDecimalDigit(current()));
5219 min = RegExpTree::kInfinity;
5220 break;
5221 }
5222 min = 10 * min + next;
5223 Advance();
5224 }
5225 int max = 0;
5226 if (current() == '}') {
5227 max = min;
5228 Advance();
5229 } else if (current() == ',') {
5230 Advance();
5231 if (current() == '}') {
5232 max = RegExpTree::kInfinity;
5233 Advance();
5234 } else {
5235 while (IsDecimalDigit(current())) {
5236 int next = current() - '0';
5237 if (max > (RegExpTree::kInfinity - next) / 10) {
5238 do {
5239 Advance();
5240 } while (IsDecimalDigit(current()));
5241 max = RegExpTree::kInfinity;
5242 break;
5243 }
5244 max = 10 * max + next;
5245 Advance();
5246 }
5247 if (current() != '}') {
5248 Reset(start);
5249 return false;
5250 }
5251 Advance();
5252 }
5253 } else {
5254 Reset(start);
5255 return false;
5256 }
5257 *min_out = min;
5258 *max_out = max;
5259 return true;
5260}
5261
5262
Steve Blocka7e24c12009-10-30 11:49:00 +00005263uc32 RegExpParser::ParseOctalLiteral() {
5264 ASSERT('0' <= current() && current() <= '7');
5265 // For compatibility with some other browsers (not all), we parse
5266 // up to three octal digits with a value below 256.
5267 uc32 value = current() - '0';
5268 Advance();
5269 if ('0' <= current() && current() <= '7') {
5270 value = value * 8 + current() - '0';
5271 Advance();
5272 if (value < 32 && '0' <= current() && current() <= '7') {
5273 value = value * 8 + current() - '0';
5274 Advance();
5275 }
5276 }
5277 return value;
5278}
5279
5280
5281bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
5282 int start = position();
5283 uc32 val = 0;
5284 bool done = false;
5285 for (int i = 0; !done; i++) {
5286 uc32 c = current();
5287 int d = HexValue(c);
5288 if (d < 0) {
5289 Reset(start);
5290 return false;
5291 }
5292 val = val * 16 + d;
5293 Advance();
5294 if (i == length - 1) {
5295 done = true;
5296 }
5297 }
5298 *value = val;
5299 return true;
5300}
5301
5302
5303uc32 RegExpParser::ParseClassCharacterEscape() {
5304 ASSERT(current() == '\\');
5305 ASSERT(has_next() && !IsSpecialClassEscape(Next()));
5306 Advance();
5307 switch (current()) {
5308 case 'b':
5309 Advance();
5310 return '\b';
5311 // ControlEscape :: one of
5312 // f n r t v
5313 case 'f':
5314 Advance();
5315 return '\f';
5316 case 'n':
5317 Advance();
5318 return '\n';
5319 case 'r':
5320 Advance();
5321 return '\r';
5322 case 't':
5323 Advance();
5324 return '\t';
5325 case 'v':
5326 Advance();
5327 return '\v';
Ben Murdoch086aeea2011-05-13 15:57:08 +01005328 case 'c': {
5329 uc32 controlLetter = Next();
5330 uc32 letter = controlLetter & ~('A' ^ 'a');
5331 // For compatibility with JSC, inside a character class
5332 // we also accept digits and underscore as control characters.
5333 if ((controlLetter >= '0' && controlLetter <= '9') ||
5334 controlLetter == '_' ||
5335 (letter >= 'A' && letter <= 'Z')) {
5336 Advance(2);
5337 // Control letters mapped to ASCII control characters in the range
5338 // 0x00-0x1f.
5339 return controlLetter & 0x1f;
5340 }
5341 // We match JSC in reading the backslash as a literal
5342 // character instead of as starting an escape.
5343 return '\\';
5344 }
Steve Blocka7e24c12009-10-30 11:49:00 +00005345 case '0': case '1': case '2': case '3': case '4': case '5':
5346 case '6': case '7':
5347 // For compatibility, we interpret a decimal escape that isn't
5348 // a back reference (and therefore either \0 or not valid according
5349 // to the specification) as a 1..3 digit octal character code.
5350 return ParseOctalLiteral();
5351 case 'x': {
5352 Advance();
5353 uc32 value;
5354 if (ParseHexEscape(2, &value)) {
5355 return value;
5356 }
5357 // If \x is not followed by a two-digit hexadecimal, treat it
5358 // as an identity escape.
5359 return 'x';
5360 }
5361 case 'u': {
5362 Advance();
5363 uc32 value;
5364 if (ParseHexEscape(4, &value)) {
5365 return value;
5366 }
5367 // If \u is not followed by a four-digit hexadecimal, treat it
5368 // as an identity escape.
5369 return 'u';
5370 }
5371 default: {
5372 // Extended identity escape. We accept any character that hasn't
5373 // been matched by a more specific case, not just the subset required
5374 // by the ECMAScript specification.
5375 uc32 result = current();
5376 Advance();
5377 return result;
5378 }
5379 }
5380 return 0;
5381}
5382
5383
5384CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
5385 ASSERT_EQ(0, *char_class);
5386 uc32 first = current();
5387 if (first == '\\') {
5388 switch (Next()) {
5389 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
5390 *char_class = Next();
5391 Advance(2);
5392 return CharacterRange::Singleton(0); // Return dummy value.
5393 }
5394 case kEndMarker:
5395 return ReportError(CStrVector("\\ at end of pattern"));
5396 default:
5397 uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
5398 return CharacterRange::Singleton(c);
5399 }
5400 } else {
5401 Advance();
5402 return CharacterRange::Singleton(first);
5403 }
5404}
5405
5406
Ben Murdochb0fe1622011-05-05 13:52:32 +01005407static const uc16 kNoCharClass = 0;
5408
5409// Adds range or pre-defined character class to character ranges.
5410// If char_class is not kInvalidClass, it's interpreted as a class
5411// escape (i.e., 's' means whitespace, from '\s').
5412static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
5413 uc16 char_class,
5414 CharacterRange range) {
5415 if (char_class != kNoCharClass) {
5416 CharacterRange::AddClassEscape(char_class, ranges);
5417 } else {
5418 ranges->Add(range);
5419 }
5420}
5421
5422
Steve Blocka7e24c12009-10-30 11:49:00 +00005423RegExpTree* RegExpParser::ParseCharacterClass() {
5424 static const char* kUnterminated = "Unterminated character class";
5425 static const char* kRangeOutOfOrder = "Range out of order in character class";
5426
5427 ASSERT_EQ(current(), '[');
5428 Advance();
5429 bool is_negated = false;
5430 if (current() == '^') {
5431 is_negated = true;
5432 Advance();
5433 }
Ben Murdoch257744e2011-11-30 15:57:28 +00005434 ZoneList<CharacterRange>* ranges = new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00005435 while (has_more() && current() != ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01005436 uc16 char_class = kNoCharClass;
Steve Blocka7e24c12009-10-30 11:49:00 +00005437 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00005438 if (current() == '-') {
5439 Advance();
5440 if (current() == kEndMarker) {
5441 // If we reach the end we break out of the loop and let the
5442 // following code report an error.
5443 break;
5444 } else if (current() == ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01005445 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00005446 ranges->Add(CharacterRange::Singleton('-'));
5447 break;
5448 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01005449 uc16 char_class_2 = kNoCharClass;
5450 CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
5451 if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
5452 // Either end is an escaped character class. Treat the '-' verbatim.
5453 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00005454 ranges->Add(CharacterRange::Singleton('-'));
Ben Murdochb0fe1622011-05-05 13:52:32 +01005455 AddRangeOrEscape(ranges, char_class_2, next);
Steve Blocka7e24c12009-10-30 11:49:00 +00005456 continue;
5457 }
5458 if (first.from() > next.to()) {
5459 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
5460 }
5461 ranges->Add(CharacterRange::Range(first.from(), next.to()));
5462 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01005463 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00005464 }
5465 }
5466 if (!has_more()) {
5467 return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
5468 }
5469 Advance();
5470 if (ranges->length() == 0) {
5471 ranges->Add(CharacterRange::Everything());
5472 is_negated = !is_negated;
5473 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01005474 return new(zone()) RegExpCharacterClass(ranges, is_negated);
Steve Blocka7e24c12009-10-30 11:49:00 +00005475}
5476
5477
5478// ----------------------------------------------------------------------------
5479// The Parser interface.
5480
Steve Blocka7e24c12009-10-30 11:49:00 +00005481ParserMessage::~ParserMessage() {
5482 for (int i = 0; i < args().length(); i++)
5483 DeleteArray(args()[i]);
5484 DeleteArray(args().start());
5485}
5486
5487
5488ScriptDataImpl::~ScriptDataImpl() {
Iain Merrick9ac36c92010-09-13 15:29:50 +01005489 if (owns_store_) store_.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00005490}
5491
5492
5493int ScriptDataImpl::Length() {
Leon Clarkef7060e22010-06-03 12:02:55 +01005494 return store_.length() * sizeof(unsigned);
Steve Blocka7e24c12009-10-30 11:49:00 +00005495}
5496
5497
Leon Clarkef7060e22010-06-03 12:02:55 +01005498const char* ScriptDataImpl::Data() {
5499 return reinterpret_cast<const char*>(store_.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00005500}
5501
5502
Leon Clarkee46be812010-01-19 14:06:41 +00005503bool ScriptDataImpl::HasError() {
5504 return has_error();
5505}
5506
5507
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005508void ScriptDataImpl::Initialize() {
5509 // Prepares state for use.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005510 if (store_.length() >= PreparseDataConstants::kHeaderSize) {
5511 function_index_ = PreparseDataConstants::kHeaderSize;
5512 int symbol_data_offset = PreparseDataConstants::kHeaderSize
5513 + store_[PreparseDataConstants::kFunctionsSizeOffset];
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005514 if (store_.length() > symbol_data_offset) {
5515 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
5516 } else {
5517 // Partial preparse causes no symbol information.
5518 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5519 }
5520 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5521 }
5522}
5523
5524
5525int ScriptDataImpl::ReadNumber(byte** source) {
5526 // Reads a number from symbol_data_ in base 128. The most significant
5527 // bit marks that there are more digits.
5528 // If the first byte is 0x80 (kNumberTerminator), it would normally
5529 // represent a leading zero. Since that is useless, and therefore won't
5530 // appear as the first digit of any actual value, it is used to
5531 // mark the end of the input stream.
5532 byte* data = *source;
5533 if (data >= symbol_data_end_) return -1;
5534 byte input = *data;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005535 if (input == PreparseDataConstants::kNumberTerminator) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005536 // End of stream marker.
5537 return -1;
5538 }
5539 int result = input & 0x7f;
5540 data++;
5541 while ((input & 0x80u) != 0) {
5542 if (data >= symbol_data_end_) return -1;
5543 input = *data;
5544 result = (result << 7) | (input & 0x7f);
5545 data++;
5546 }
5547 *source = data;
5548 return result;
5549}
5550
5551
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005552// Create a Scanner for the preparser to use as input, and preparse the source.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005553static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005554 int flags,
5555 ParserRecorder* recorder) {
Steve Block44f0eee2011-05-26 01:26:41 +01005556 Isolate* isolate = Isolate::Current();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005557 HistogramTimerScope timer(isolate->counters()->pre_parse());
5558 Scanner scanner(isolate->unicode_cache());
5559 scanner.SetHarmonyScoping(FLAG_harmony_scoping);
Steve Block9fac8402011-05-12 15:51:54 +01005560 scanner.Initialize(source);
Steve Block44f0eee2011-05-26 01:26:41 +01005561 intptr_t stack_limit = isolate->stack_guard()->real_climit();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005562 preparser::PreParser::PreParseResult result =
5563 preparser::PreParser::PreParseProgram(&scanner,
5564 recorder,
5565 flags,
5566 stack_limit);
5567 if (result == preparser::PreParser::kPreParseStackOverflow) {
Steve Block44f0eee2011-05-26 01:26:41 +01005568 isolate->StackOverflow();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005569 return NULL;
5570 }
5571
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005572 // Extract the accumulated data from the recorder as a single
5573 // contiguous vector that we are responsible for disposing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005574 Vector<unsigned> store = recorder->ExtractData();
Steve Blocka7e24c12009-10-30 11:49:00 +00005575 return new ScriptDataImpl(store);
5576}
5577
5578
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005579// Preparse, but only collect data that is immediately useful,
5580// even if the preparser data is only used once.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005581ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005582 v8::Extension* extension,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005583 int flags) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005584 bool allow_lazy = FLAG_lazy && (extension == NULL);
5585 if (!allow_lazy) {
5586 // Partial preparsing is only about lazily compiled functions.
5587 // If we don't allow lazy compilation, the log data will be empty.
5588 return NULL;
5589 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005590 flags |= kAllowLazy;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005591 PartialParserRecorder recorder;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005592 int source_length = source->length();
5593 if (source->IsExternalTwoByteString()) {
5594 ExternalTwoByteStringUC16CharacterStream stream(
5595 Handle<ExternalTwoByteString>::cast(source), 0, source_length);
5596 return DoPreParse(&stream, flags, &recorder);
5597 } else {
5598 GenericStringUC16CharacterStream stream(source, 0, source_length);
5599 return DoPreParse(&stream, flags, &recorder);
5600 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005601}
5602
5603
Ben Murdochb0fe1622011-05-05 13:52:32 +01005604ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005605 v8::Extension* extension,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005606 int flags) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005607 Handle<Script> no_script;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005608 if (FLAG_lazy && (extension == NULL)) {
5609 flags |= kAllowLazy;
5610 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005611 CompleteParserRecorder recorder;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005612 return DoPreParse(source, flags, &recorder);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005613}
5614
5615
5616bool RegExpParser::ParseRegExp(FlatStringReader* input,
5617 bool multiline,
5618 RegExpCompileData* result) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005619 ASSERT(result != NULL);
5620 RegExpParser parser(input, &result->error, multiline);
5621 RegExpTree* tree = parser.ParsePattern();
5622 if (parser.failed()) {
5623 ASSERT(tree == NULL);
5624 ASSERT(!result->error.is_null());
5625 } else {
5626 ASSERT(tree != NULL);
5627 ASSERT(result->error.is_null());
5628 result->tree = tree;
5629 int capture_count = parser.captures_started();
5630 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
5631 result->contains_anchor = parser.contains_anchor();
5632 result->capture_count = capture_count;
5633 }
5634 return !parser.failed();
5635}
5636
5637
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005638bool ParserApi::Parse(CompilationInfo* info, int parsing_flags) {
Ben Murdochf87a2032010-10-22 12:50:53 +01005639 ASSERT(info->function() == NULL);
5640 FunctionLiteral* result = NULL;
5641 Handle<Script> script = info->script();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005642 ASSERT((parsing_flags & kLanguageModeMask) == CLASSIC_MODE);
5643 if (!info->is_native() && FLAG_harmony_scoping) {
5644 // Harmony scoping is requested.
5645 parsing_flags |= EXTENDED_MODE;
5646 }
5647 if (FLAG_allow_natives_syntax || info->is_native()) {
5648 // We requre %identifier(..) syntax.
5649 parsing_flags |= kAllowNativesSyntax;
5650 }
Ben Murdochf87a2032010-10-22 12:50:53 +01005651 if (info->is_lazy()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005652 ASSERT(!info->is_eval());
5653 Parser parser(script, parsing_flags, NULL, NULL);
Steve Block44f0eee2011-05-26 01:26:41 +01005654 result = parser.ParseLazy(info);
Leon Clarke4515c472010-02-03 11:58:03 +00005655 } else {
Ben Murdochf87a2032010-10-22 12:50:53 +01005656 ScriptDataImpl* pre_data = info->pre_parse_data();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005657 Parser parser(script, parsing_flags, info->extension(), pre_data);
Ben Murdochf87a2032010-10-22 12:50:53 +01005658 if (pre_data != NULL && pre_data->has_error()) {
5659 Scanner::Location loc = pre_data->MessageLocation();
5660 const char* message = pre_data->BuildMessage();
5661 Vector<const char*> args = pre_data->BuildArgs();
5662 parser.ReportMessageAt(loc, message, args);
5663 DeleteArray(message);
5664 for (int i = 0; i < args.length(); i++) {
5665 DeleteArray(args[i]);
5666 }
5667 DeleteArray(args.start());
Steve Block44f0eee2011-05-26 01:26:41 +01005668 ASSERT(info->isolate()->has_pending_exception());
Ben Murdochf87a2032010-10-22 12:50:53 +01005669 } else {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005670 result = parser.ParseProgram(info);
Ben Murdochf87a2032010-10-22 12:50:53 +01005671 }
Leon Clarke4515c472010-02-03 11:58:03 +00005672 }
Ben Murdochf87a2032010-10-22 12:50:53 +01005673 info->SetFunction(result);
5674 return (result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00005675}
5676
Steve Blocka7e24c12009-10-30 11:49:00 +00005677} } // namespace v8::internal