blob: 35cc1c92d9ed911415846ab64eeb7de593d26dde [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.
Ben Murdochc7cc0282012-03-05 14:35:55 +00001189 ExpressionStatement* e_stat;
1190 Literal* literal;
Steve Block1e0659c2011-05-24 12:43:12 +01001191 // 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
Ben Murdochc7cc0282012-03-05 14:35:55 +00001565 // other functions are set up 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 }
Ben Murdochc7cc0282012-03-05 14:35:55 +00002698 MarkAsLValue(expression);
Steve Block1e0659c2011-05-24 12:43:12 +01002699
Steve Blocka7e24c12009-10-30 11:49:00 +00002700 Token::Value op = Next(); // Get assignment operator.
2701 int pos = scanner().location().beg_pos;
2702 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2703
2704 // TODO(1231235): We try to estimate the set of properties set by
2705 // constructors. We define a new property whenever there is an
2706 // assignment to a property of 'this'. We should probably only add
2707 // properties if we haven't seen them before. Otherwise we'll
2708 // probably overestimate the number of properties.
2709 Property* property = expression ? expression->AsProperty() : NULL;
2710 if (op == Token::ASSIGN &&
2711 property != NULL &&
2712 property->obj()->AsVariableProxy() != NULL &&
2713 property->obj()->AsVariableProxy()->is_this()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002714 current_function_state_->AddProperty();
Steve Blocka7e24c12009-10-30 11:49:00 +00002715 }
2716
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002717 // If we assign a function literal to a property we pretenure the
2718 // literal so it can be added as a constant function property.
2719 if (property != NULL && right->AsFunctionLiteral() != NULL) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002720 right->AsFunctionLiteral()->set_pretenure();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002721 }
2722
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002723 if (fni_ != NULL) {
2724 // Check if the right hand side is a call to avoid inferring a
2725 // name if we're dealing with "a = function(){...}();"-like
2726 // expression.
2727 if ((op == Token::INIT_VAR
2728 || op == Token::INIT_CONST
2729 || op == Token::ASSIGN)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002730 && (right->AsCall() == NULL && right->AsCallNew() == NULL)) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002731 fni_->Infer();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002732 } else {
2733 fni_->RemoveLastFunction();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002734 }
2735 fni_->Leave();
2736 }
2737
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002738 return new(zone()) Assignment(isolate(), op, expression, right, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002739}
2740
2741
2742// Precedence = 3
2743Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
2744 // ConditionalExpression ::
2745 // LogicalOrExpression
2746 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
2747
2748 // We start using the binary expression parser for prec >= 4 only!
2749 Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
2750 if (peek() != Token::CONDITIONAL) return expression;
2751 Consume(Token::CONDITIONAL);
2752 // In parsing the first assignment expression in conditional
2753 // expressions we always accept the 'in' keyword; see ECMA-262,
2754 // section 11.12, page 58.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002755 int left_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002756 Expression* left = ParseAssignmentExpression(true, CHECK_OK);
2757 Expect(Token::COLON, CHECK_OK);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002758 int right_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002759 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002760 return new(zone()) Conditional(
2761 isolate(), expression, left, right, left_position, right_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002762}
2763
2764
2765static int Precedence(Token::Value tok, bool accept_IN) {
2766 if (tok == Token::IN && !accept_IN)
2767 return 0; // 0 precedence will terminate binary expression parsing
2768
2769 return Token::Precedence(tok);
2770}
2771
2772
2773// Precedence >= 4
2774Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
2775 ASSERT(prec >= 4);
2776 Expression* x = ParseUnaryExpression(CHECK_OK);
2777 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
2778 // prec1 >= 4
2779 while (Precedence(peek(), accept_IN) == prec1) {
2780 Token::Value op = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002781 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002782 Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
2783
2784 // Compute some expressions involving only number literals.
2785 if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
2786 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
2787 double x_val = x->AsLiteral()->handle()->Number();
2788 double y_val = y->AsLiteral()->handle()->Number();
2789
2790 switch (op) {
2791 case Token::ADD:
2792 x = NewNumberLiteral(x_val + y_val);
2793 continue;
2794 case Token::SUB:
2795 x = NewNumberLiteral(x_val - y_val);
2796 continue;
2797 case Token::MUL:
2798 x = NewNumberLiteral(x_val * y_val);
2799 continue;
2800 case Token::DIV:
2801 x = NewNumberLiteral(x_val / y_val);
2802 continue;
2803 case Token::BIT_OR:
2804 x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
2805 continue;
2806 case Token::BIT_AND:
2807 x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
2808 continue;
2809 case Token::BIT_XOR:
2810 x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
2811 continue;
2812 case Token::SHL: {
2813 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
2814 x = NewNumberLiteral(value);
2815 continue;
2816 }
2817 case Token::SHR: {
2818 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2819 uint32_t value = DoubleToUint32(x_val) >> shift;
2820 x = NewNumberLiteral(value);
2821 continue;
2822 }
2823 case Token::SAR: {
2824 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2825 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
2826 x = NewNumberLiteral(value);
2827 continue;
2828 }
2829 default:
2830 break;
2831 }
2832 }
2833
Steve Blocka7e24c12009-10-30 11:49:00 +00002834 // For now we distinguish between comparisons and other binary
2835 // operations. (We could combine the two and get rid of this
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002836 // code and AST node eventually.)
Steve Blocka7e24c12009-10-30 11:49:00 +00002837 if (Token::IsCompareOp(op)) {
2838 // We have a comparison.
2839 Token::Value cmp = op;
2840 switch (op) {
2841 case Token::NE: cmp = Token::EQ; break;
2842 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
2843 default: break;
2844 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002845 x = new(zone()) CompareOperation(isolate(), cmp, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002846 if (cmp != op) {
2847 // The comparison was negated - add a NOT.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002848 x = new(zone()) UnaryOperation(isolate(), Token::NOT, x, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002849 }
2850
2851 } else {
2852 // We have a "normal" binary operation.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002853 x = new(zone()) BinaryOperation(isolate(), op, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002854 }
2855 }
2856 }
2857 return x;
2858}
2859
2860
2861Expression* Parser::ParseUnaryExpression(bool* ok) {
2862 // UnaryExpression ::
2863 // PostfixExpression
2864 // 'delete' UnaryExpression
2865 // 'void' UnaryExpression
2866 // 'typeof' UnaryExpression
2867 // '++' UnaryExpression
2868 // '--' UnaryExpression
2869 // '+' UnaryExpression
2870 // '-' UnaryExpression
2871 // '~' UnaryExpression
2872 // '!' UnaryExpression
2873
2874 Token::Value op = peek();
2875 if (Token::IsUnaryOp(op)) {
2876 op = Next();
Ben Murdoch257744e2011-11-30 15:57:28 +00002877 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002878 Expression* expression = ParseUnaryExpression(CHECK_OK);
2879
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002880 if (expression != NULL && (expression->AsLiteral() != NULL)) {
2881 Handle<Object> literal = expression->AsLiteral()->handle();
2882 if (op == Token::NOT) {
2883 // Convert the literal to a boolean condition and negate it.
2884 bool condition = literal->ToBoolean()->IsTrue();
2885 Handle<Object> result(isolate()->heap()->ToBoolean(!condition));
2886 return NewLiteral(result);
2887 } else if (literal->IsNumber()) {
2888 // Compute some expressions involving only number literals.
2889 double value = literal->Number();
2890 switch (op) {
2891 case Token::ADD:
2892 return expression;
2893 case Token::SUB:
2894 return NewNumberLiteral(-value);
2895 case Token::BIT_NOT:
2896 return NewNumberLiteral(~DoubleToInt32(value));
2897 default:
2898 break;
2899 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002900 }
2901 }
2902
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002903 // "delete identifier" is a syntax error in strict mode.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002904 if (op == Token::DELETE && !top_scope_->is_classic_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002905 VariableProxy* operand = expression->AsVariableProxy();
2906 if (operand != NULL && !operand->is_this()) {
2907 ReportMessage("strict_delete", Vector<const char*>::empty());
2908 *ok = false;
2909 return NULL;
2910 }
2911 }
2912
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002913 return new(zone()) UnaryOperation(isolate(), op, expression, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002914
2915 } else if (Token::IsCountOp(op)) {
2916 op = Next();
2917 Expression* expression = ParseUnaryExpression(CHECK_OK);
2918 // Signal a reference error if the expression is an invalid
2919 // left-hand side expression. We could report this as a syntax
2920 // error here but for compatibility with JSC we choose to report the
2921 // error at runtime.
2922 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002923 Handle<String> type =
2924 isolate()->factory()->invalid_lhs_in_prefix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002925 expression = NewThrowReferenceError(type);
2926 }
Steve Block1e0659c2011-05-24 12:43:12 +01002927
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002928 if (!top_scope_->is_classic_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002929 // Prefix expression operand in strict mode may not be eval or arguments.
2930 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2931 }
Ben Murdochc7cc0282012-03-05 14:35:55 +00002932 MarkAsLValue(expression);
Steve Block1e0659c2011-05-24 12:43:12 +01002933
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002934 int position = scanner().location().beg_pos;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002935 return new(zone()) CountOperation(isolate(),
2936 op,
Ben Murdoch8b112d22011-06-08 16:22:53 +01002937 true /* prefix */,
2938 expression,
2939 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002940
2941 } else {
2942 return ParsePostfixExpression(ok);
2943 }
2944}
2945
2946
2947Expression* Parser::ParsePostfixExpression(bool* ok) {
2948 // PostfixExpression ::
2949 // LeftHandSideExpression ('++' | '--')?
2950
2951 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002952 if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Ben Murdochb0fe1622011-05-05 13:52:32 +01002953 Token::IsCountOp(peek())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002954 // Signal a reference error if the expression is an invalid
2955 // left-hand side expression. We could report this as a syntax
2956 // error here but for compatibility with JSC we choose to report the
2957 // error at runtime.
2958 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002959 Handle<String> type =
2960 isolate()->factory()->invalid_lhs_in_postfix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002961 expression = NewThrowReferenceError(type);
2962 }
Steve Block1e0659c2011-05-24 12:43:12 +01002963
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002964 if (!top_scope_->is_classic_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002965 // Postfix expression operand in strict mode may not be eval or arguments.
2966 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2967 }
Ben Murdochc7cc0282012-03-05 14:35:55 +00002968 MarkAsLValue(expression);
Steve Block1e0659c2011-05-24 12:43:12 +01002969
Steve Blocka7e24c12009-10-30 11:49:00 +00002970 Token::Value next = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002971 int position = scanner().location().beg_pos;
Ben Murdoch8b112d22011-06-08 16:22:53 +01002972 expression =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002973 new(zone()) CountOperation(isolate(),
2974 next,
Ben Murdoch8b112d22011-06-08 16:22:53 +01002975 false /* postfix */,
2976 expression,
2977 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002978 }
2979 return expression;
2980}
2981
2982
2983Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
2984 // LeftHandSideExpression ::
2985 // (NewExpression | MemberExpression) ...
2986
2987 Expression* result;
2988 if (peek() == Token::NEW) {
2989 result = ParseNewExpression(CHECK_OK);
2990 } else {
2991 result = ParseMemberExpression(CHECK_OK);
2992 }
2993
2994 while (true) {
2995 switch (peek()) {
2996 case Token::LBRACK: {
2997 Consume(Token::LBRACK);
2998 int pos = scanner().location().beg_pos;
2999 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003000 result = new(zone()) Property(isolate(), result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00003001 Expect(Token::RBRACK, CHECK_OK);
3002 break;
3003 }
3004
3005 case Token::LPAREN: {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003006 int pos;
3007 if (scanner().current_token() == Token::IDENTIFIER) {
3008 // For call of an identifier we want to report position of
3009 // the identifier as position of the call in the stack trace.
3010 pos = scanner().location().beg_pos;
3011 } else {
3012 // For other kinds of calls we record position of the parenthesis as
3013 // position of the call. Note that this is extremely important for
3014 // expressions of the form function(){...}() for which call position
3015 // should not point to the closing brace otherwise it will intersect
3016 // with positions recorded for function literal and confuse debugger.
3017 pos = scanner().peek_location().beg_pos;
3018 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003019 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
3020
3021 // Keep track of eval() calls since they disable all local variable
3022 // optimizations.
3023 // The calls that need special treatment are the
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003024 // direct eval calls. These calls are all of the form eval(...), with
3025 // no explicit receiver.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003026 // These calls are marked as potentially direct eval calls. Whether
3027 // they are actually direct calls to eval is determined at run time.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003028 VariableProxy* callee = result->AsVariableProxy();
Steve Block44f0eee2011-05-26 01:26:41 +01003029 if (callee != NULL &&
3030 callee->IsVariable(isolate()->factory()->eval_symbol())) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003031 top_scope_->DeclarationScope()->RecordEvalCall();
Steve Blocka7e24c12009-10-30 11:49:00 +00003032 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003033 result = NewCall(result, args, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00003034 break;
3035 }
3036
3037 case Token::PERIOD: {
3038 Consume(Token::PERIOD);
3039 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01003040 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003041 result = new(zone()) Property(isolate(),
3042 result,
3043 NewLiteral(name),
3044 pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003045 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003046 break;
3047 }
3048
3049 default:
3050 return result;
3051 }
3052 }
3053}
3054
3055
Steve Blocka7e24c12009-10-30 11:49:00 +00003056Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
3057 // NewExpression ::
3058 // ('new')+ MemberExpression
3059
3060 // The grammar for new expressions is pretty warped. The keyword
3061 // 'new' can either be a part of the new expression (where it isn't
3062 // followed by an argument list) or a part of the member expression,
3063 // where it must be followed by an argument list. To accommodate
3064 // this, we parse the 'new' keywords greedily and keep track of how
3065 // many we have parsed. This information is then passed on to the
3066 // member expression parser, which is only allowed to match argument
3067 // lists as long as it has 'new' prefixes left
3068 Expect(Token::NEW, CHECK_OK);
3069 PositionStack::Element pos(stack, scanner().location().beg_pos);
3070
3071 Expression* result;
3072 if (peek() == Token::NEW) {
3073 result = ParseNewPrefix(stack, CHECK_OK);
3074 } else {
3075 result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
3076 }
3077
3078 if (!stack->is_empty()) {
3079 int last = stack->pop();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003080 result = new(zone()) CallNew(isolate(),
3081 result,
Ben Murdoch257744e2011-11-30 15:57:28 +00003082 new(zone()) ZoneList<Expression*>(0),
3083 last);
Steve Blocka7e24c12009-10-30 11:49:00 +00003084 }
3085 return result;
3086}
3087
3088
3089Expression* Parser::ParseNewExpression(bool* ok) {
3090 PositionStack stack(ok);
3091 return ParseNewPrefix(&stack, ok);
3092}
3093
3094
3095Expression* Parser::ParseMemberExpression(bool* ok) {
3096 return ParseMemberWithNewPrefixesExpression(NULL, ok);
3097}
3098
3099
3100Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
3101 bool* ok) {
3102 // MemberExpression ::
3103 // (PrimaryExpression | FunctionLiteral)
3104 // ('[' Expression ']' | '.' Identifier | Arguments)*
3105
3106 // Parse the initial primary or function expression.
3107 Expression* result = NULL;
3108 if (peek() == Token::FUNCTION) {
3109 Expect(Token::FUNCTION, CHECK_OK);
3110 int function_token_position = scanner().location().beg_pos;
3111 Handle<String> name;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003112 bool is_strict_reserved_name = false;
Steve Block1e0659c2011-05-24 12:43:12 +01003113 if (peek_any_identifier()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003114 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
3115 CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003116 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003117 FunctionLiteral::Type type = name.is_null()
3118 ? FunctionLiteral::ANONYMOUS_EXPRESSION
3119 : FunctionLiteral::NAMED_EXPRESSION;
3120 result = ParseFunctionLiteral(name,
3121 is_strict_reserved_name,
3122 function_token_position,
3123 type,
3124 CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003125 } else {
3126 result = ParsePrimaryExpression(CHECK_OK);
3127 }
3128
3129 while (true) {
3130 switch (peek()) {
3131 case Token::LBRACK: {
3132 Consume(Token::LBRACK);
3133 int pos = scanner().location().beg_pos;
3134 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003135 result = new(zone()) Property(isolate(), result, index, pos);
3136 if (fni_ != NULL) {
3137 if (index->IsPropertyName()) {
3138 fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
3139 } else {
3140 fni_->PushLiteralName(
3141 isolate()->factory()->anonymous_function_symbol());
3142 }
3143 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003144 Expect(Token::RBRACK, CHECK_OK);
3145 break;
3146 }
3147 case Token::PERIOD: {
3148 Consume(Token::PERIOD);
3149 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01003150 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003151 result = new(zone()) Property(isolate(),
3152 result,
3153 NewLiteral(name),
3154 pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003155 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003156 break;
3157 }
3158 case Token::LPAREN: {
3159 if ((stack == NULL) || stack->is_empty()) return result;
3160 // Consume one of the new prefixes (already parsed).
3161 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
3162 int last = stack->pop();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003163 result = new(zone()) CallNew(isolate(), result, args, last);
Steve Blocka7e24c12009-10-30 11:49:00 +00003164 break;
3165 }
3166 default:
3167 return result;
3168 }
3169 }
3170}
3171
3172
3173DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
3174 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
3175 // contexts this is used as a statement which invokes the debugger as i a
3176 // break point is present.
3177 // DebuggerStatement ::
3178 // 'debugger' ';'
3179
3180 Expect(Token::DEBUGGER, CHECK_OK);
3181 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003182 return new(zone()) DebuggerStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00003183}
3184
3185
3186void Parser::ReportUnexpectedToken(Token::Value token) {
3187 // We don't report stack overflows here, to avoid increasing the
3188 // stack depth even further. Instead we report it after parsing is
Leon Clarke4515c472010-02-03 11:58:03 +00003189 // over, in ParseProgram/ParseJson.
Ben Murdochb0fe1622011-05-05 13:52:32 +01003190 if (token == Token::ILLEGAL && stack_overflow_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00003191 // Four of the tokens are treated specially
3192 switch (token) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003193 case Token::EOS:
3194 return ReportMessage("unexpected_eos", Vector<const char*>::empty());
3195 case Token::NUMBER:
3196 return ReportMessage("unexpected_token_number",
3197 Vector<const char*>::empty());
3198 case Token::STRING:
3199 return ReportMessage("unexpected_token_string",
3200 Vector<const char*>::empty());
3201 case Token::IDENTIFIER:
3202 return ReportMessage("unexpected_token_identifier",
3203 Vector<const char*>::empty());
Steve Block1e0659c2011-05-24 12:43:12 +01003204 case Token::FUTURE_RESERVED_WORD:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003205 return ReportMessage("unexpected_reserved",
3206 Vector<const char*>::empty());
3207 case Token::FUTURE_STRICT_RESERVED_WORD:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003208 return ReportMessage(top_scope_->is_classic_mode() ?
3209 "unexpected_token_identifier" :
3210 "unexpected_strict_reserved",
Steve Block1e0659c2011-05-24 12:43:12 +01003211 Vector<const char*>::empty());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003212 default:
3213 const char* name = Token::String(token);
3214 ASSERT(name != NULL);
3215 ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00003216 }
3217}
3218
3219
Leon Clarkeac952652010-07-15 11:15:24 +01003220void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
Ben Murdoch589d6972011-11-30 16:04:58 +00003221 SmartArrayPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
Leon Clarkeac952652010-07-15 11:15:24 +01003222 const char* element[1] = { *name_string };
3223 ReportMessage("invalid_preparser_data",
3224 Vector<const char*>(element, 1));
3225 *ok = false;
3226}
3227
3228
Steve Blocka7e24c12009-10-30 11:49:00 +00003229Expression* Parser::ParsePrimaryExpression(bool* ok) {
3230 // PrimaryExpression ::
3231 // 'this'
3232 // 'null'
3233 // 'true'
3234 // 'false'
3235 // Identifier
3236 // Number
3237 // String
3238 // ArrayLiteral
3239 // ObjectLiteral
3240 // RegExpLiteral
3241 // '(' Expression ')'
3242
3243 Expression* result = NULL;
3244 switch (peek()) {
3245 case Token::THIS: {
3246 Consume(Token::THIS);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003247 result = new(zone()) VariableProxy(isolate(), top_scope_->receiver());
Steve Blocka7e24c12009-10-30 11:49:00 +00003248 break;
3249 }
3250
3251 case Token::NULL_LITERAL:
3252 Consume(Token::NULL_LITERAL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003253 result = new(zone()) Literal(
3254 isolate(), isolate()->factory()->null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003255 break;
3256
3257 case Token::TRUE_LITERAL:
3258 Consume(Token::TRUE_LITERAL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003259 result = new(zone()) Literal(
3260 isolate(), isolate()->factory()->true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003261 break;
3262
3263 case Token::FALSE_LITERAL:
3264 Consume(Token::FALSE_LITERAL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003265 result = new(zone()) Literal(
3266 isolate(), isolate()->factory()->false_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003267 break;
3268
Steve Block1e0659c2011-05-24 12:43:12 +01003269 case Token::IDENTIFIER:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003270 case Token::FUTURE_STRICT_RESERVED_WORD: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003271 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003272 if (fni_ != NULL) fni_->PushVariableName(name);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003273 result = top_scope_->NewUnresolved(name, scanner().location().beg_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00003274 break;
3275 }
3276
3277 case Token::NUMBER: {
3278 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003279 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01003280 double value = StringToDouble(isolate()->unicode_cache(),
3281 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01003282 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003283 result = NewNumberLiteral(value);
3284 break;
3285 }
3286
3287 case Token::STRING: {
3288 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003289 Handle<String> symbol = GetSymbol(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003290 result = NewLiteral(symbol);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003291 if (fni_ != NULL) fni_->PushLiteralName(symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00003292 break;
3293 }
3294
3295 case Token::ASSIGN_DIV:
3296 result = ParseRegExpLiteral(true, CHECK_OK);
3297 break;
3298
3299 case Token::DIV:
3300 result = ParseRegExpLiteral(false, CHECK_OK);
3301 break;
3302
3303 case Token::LBRACK:
3304 result = ParseArrayLiteral(CHECK_OK);
3305 break;
3306
3307 case Token::LBRACE:
3308 result = ParseObjectLiteral(CHECK_OK);
3309 break;
3310
3311 case Token::LPAREN:
3312 Consume(Token::LPAREN);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003313 // Heuristically try to detect immediately called functions before
3314 // seeing the call parentheses.
3315 parenthesized_function_ = (peek() == Token::FUNCTION);
Steve Blocka7e24c12009-10-30 11:49:00 +00003316 result = ParseExpression(true, CHECK_OK);
3317 Expect(Token::RPAREN, CHECK_OK);
3318 break;
3319
3320 case Token::MOD:
3321 if (allow_natives_syntax_ || extension_ != NULL) {
3322 result = ParseV8Intrinsic(CHECK_OK);
3323 break;
3324 }
3325 // If we're not allowing special syntax we fall-through to the
3326 // default case.
3327
3328 default: {
Ben Murdochbb769b22010-08-11 14:56:33 +01003329 Token::Value tok = Next();
Steve Blocka7e24c12009-10-30 11:49:00 +00003330 ReportUnexpectedToken(tok);
3331 *ok = false;
3332 return NULL;
3333 }
3334 }
3335
3336 return result;
3337}
3338
3339
Leon Clarke4515c472010-02-03 11:58:03 +00003340void Parser::BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* values,
3341 Handle<FixedArray> literals,
3342 bool* is_simple,
3343 int* depth) {
3344 // Fill in the literals.
3345 // Accumulate output values in local variables.
3346 bool is_simple_acc = true;
3347 int depth_acc = 1;
3348 for (int i = 0; i < values->length(); i++) {
3349 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
3350 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3351 depth_acc = m_literal->depth() + 1;
3352 }
3353 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
3354 if (boilerplate_value->IsUndefined()) {
3355 literals->set_the_hole(i);
3356 is_simple_acc = false;
3357 } else {
3358 literals->set(i, *boilerplate_value);
3359 }
3360 }
3361
3362 *is_simple = is_simple_acc;
3363 *depth = depth_acc;
3364}
3365
3366
Steve Blocka7e24c12009-10-30 11:49:00 +00003367Expression* Parser::ParseArrayLiteral(bool* ok) {
3368 // ArrayLiteral ::
3369 // '[' Expression? (',' Expression?)* ']'
3370
Ben Murdoch257744e2011-11-30 15:57:28 +00003371 ZoneList<Expression*>* values = new(zone()) ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003372 Expect(Token::LBRACK, CHECK_OK);
3373 while (peek() != Token::RBRACK) {
3374 Expression* elem;
3375 if (peek() == Token::COMMA) {
3376 elem = GetLiteralTheHole();
3377 } else {
3378 elem = ParseAssignmentExpression(true, CHECK_OK);
3379 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003380 values->Add(elem);
Steve Blocka7e24c12009-10-30 11:49:00 +00003381 if (peek() != Token::RBRACK) {
3382 Expect(Token::COMMA, CHECK_OK);
3383 }
3384 }
3385 Expect(Token::RBRACK, CHECK_OK);
3386
3387 // Update the scope information before the pre-parsing bailout.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003388 int literal_index = current_function_state_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003389
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003390 // Allocate a fixed array to hold all the object literals.
3391 Handle<FixedArray> object_literals =
Steve Block44f0eee2011-05-26 01:26:41 +01003392 isolate()->factory()->NewFixedArray(values->length(), TENURED);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003393 Handle<FixedDoubleArray> double_literals;
3394 ElementsKind elements_kind = FAST_SMI_ONLY_ELEMENTS;
Ben Murdochc7cc0282012-03-05 14:35:55 +00003395 bool has_only_undefined_values = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003396
3397 // Fill in the literals.
3398 bool is_simple = true;
3399 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003400 for (int i = 0, n = values->length(); i < n; i++) {
3401 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
Steve Blocka7e24c12009-10-30 11:49:00 +00003402 if (m_literal != NULL && m_literal->depth() + 1 > depth) {
3403 depth = m_literal->depth() + 1;
3404 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003405 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00003406 if (boilerplate_value->IsUndefined()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003407 object_literals->set_the_hole(i);
3408 if (elements_kind == FAST_DOUBLE_ELEMENTS) {
3409 double_literals->set_the_hole(i);
3410 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003411 is_simple = false;
3412 } else {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003413 // Examine each literal element, and adjust the ElementsKind if the
3414 // literal element is not of a type that can be stored in the current
3415 // ElementsKind. Start with FAST_SMI_ONLY_ELEMENTS, and transition to
3416 // FAST_DOUBLE_ELEMENTS and FAST_ELEMENTS as necessary. Always remember
3417 // the tagged value, no matter what the ElementsKind is in case we
3418 // ultimately end up in FAST_ELEMENTS.
Ben Murdochc7cc0282012-03-05 14:35:55 +00003419 has_only_undefined_values = false;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003420 object_literals->set(i, *boilerplate_value);
3421 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
3422 // Smi only elements. Notice if a transition to FAST_DOUBLE_ELEMENTS or
3423 // FAST_ELEMENTS is required.
3424 if (!boilerplate_value->IsSmi()) {
3425 if (boilerplate_value->IsNumber() && FLAG_smi_only_arrays) {
3426 // Allocate a double array on the FAST_DOUBLE_ELEMENTS transition to
3427 // avoid over-allocating in TENURED space.
3428 double_literals = isolate()->factory()->NewFixedDoubleArray(
3429 values->length(), TENURED);
3430 // Copy the contents of the FAST_SMI_ONLY_ELEMENT array to the
3431 // FAST_DOUBLE_ELEMENTS array so that they are in sync.
3432 for (int j = 0; j < i; ++j) {
3433 Object* smi_value = object_literals->get(j);
3434 if (smi_value->IsTheHole()) {
3435 double_literals->set_the_hole(j);
3436 } else {
3437 double_literals->set(j, Smi::cast(smi_value)->value());
3438 }
3439 }
3440 double_literals->set(i, boilerplate_value->Number());
3441 elements_kind = FAST_DOUBLE_ELEMENTS;
3442 } else {
3443 elements_kind = FAST_ELEMENTS;
3444 }
3445 }
3446 } else if (elements_kind == FAST_DOUBLE_ELEMENTS) {
3447 // Continue to store double values in to FAST_DOUBLE_ELEMENTS arrays
3448 // until the first value is seen that can't be stored as a double.
3449 if (boilerplate_value->IsNumber()) {
3450 double_literals->set(i, boilerplate_value->Number());
3451 } else {
3452 elements_kind = FAST_ELEMENTS;
3453 }
3454 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003455 }
3456 }
3457
Ben Murdochc7cc0282012-03-05 14:35:55 +00003458 // Very small array literals that don't have a concrete hint about their type
3459 // from a constant value should default to the slow case to avoid lots of
3460 // elements transitions on really small objects.
3461 if (has_only_undefined_values && values->length() <= 2) {
3462 elements_kind = FAST_ELEMENTS;
3463 }
3464
Iain Merrick75681382010-08-19 15:07:18 +01003465 // Simple and shallow arrays can be lazily copied, we transform the
3466 // elements array to a copy-on-write array.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003467 if (is_simple && depth == 1 && values->length() > 0 &&
3468 elements_kind != FAST_DOUBLE_ELEMENTS) {
3469 object_literals->set_map(isolate()->heap()->fixed_cow_array_map());
Iain Merrick75681382010-08-19 15:07:18 +01003470 }
3471
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003472 Handle<FixedArrayBase> element_values = elements_kind == FAST_DOUBLE_ELEMENTS
3473 ? Handle<FixedArrayBase>(double_literals)
3474 : Handle<FixedArrayBase>(object_literals);
3475
3476 // Remember both the literal's constant values as well as the ElementsKind
3477 // in a 2-element FixedArray.
3478 Handle<FixedArray> literals =
3479 isolate()->factory()->NewFixedArray(2, TENURED);
3480
3481 literals->set(0, Smi::FromInt(elements_kind));
3482 literals->set(1, *element_values);
3483
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003484 return new(zone()) ArrayLiteral(
3485 isolate(), literals, values, literal_index, is_simple, depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003486}
3487
3488
3489bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
3490 return property != NULL &&
3491 property->kind() != ObjectLiteral::Property::PROTOTYPE;
3492}
3493
3494
3495bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003496 if (expression->AsLiteral() != NULL) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003497 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3498 return lit != NULL && lit->is_simple();
3499}
3500
Iain Merrick75681382010-08-19 15:07:18 +01003501
3502bool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
3503 Expression* value) {
3504 // If value is a literal the property value is already set in the
3505 // boilerplate object.
3506 if (value->AsLiteral() != NULL) return false;
3507 // If value is a materialized literal the property value is already set
3508 // in the boilerplate object if it is simple.
3509 if (CompileTimeValue::IsCompileTimeValue(value)) return false;
3510 return true;
3511}
3512
3513
Steve Blocka7e24c12009-10-30 11:49:00 +00003514Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
3515 ASSERT(IsCompileTimeValue(expression));
Steve Block44f0eee2011-05-26 01:26:41 +01003516 Handle<FixedArray> result = FACTORY->NewFixedArray(2, TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003517 ObjectLiteral* object_literal = expression->AsObjectLiteral();
3518 if (object_literal != NULL) {
3519 ASSERT(object_literal->is_simple());
Steve Block6ded16b2010-05-10 14:33:55 +01003520 if (object_literal->fast_elements()) {
3521 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3522 } else {
3523 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3524 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003525 result->set(kElementsSlot, *object_literal->constant_properties());
3526 } else {
3527 ArrayLiteral* array_literal = expression->AsArrayLiteral();
3528 ASSERT(array_literal != NULL && array_literal->is_simple());
3529 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
Leon Clarkee46be812010-01-19 14:06:41 +00003530 result->set(kElementsSlot, *array_literal->constant_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00003531 }
3532 return result;
3533}
3534
3535
3536CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
3537 Smi* type_value = Smi::cast(value->get(kTypeSlot));
3538 return static_cast<Type>(type_value->value());
3539}
3540
3541
3542Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3543 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3544}
3545
3546
3547Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
3548 if (expression->AsLiteral() != NULL) {
3549 return expression->AsLiteral()->handle();
3550 }
3551 if (CompileTimeValue::IsCompileTimeValue(expression)) {
3552 return CompileTimeValue::GetValue(expression);
3553 }
Steve Block44f0eee2011-05-26 01:26:41 +01003554 return isolate()->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003555}
3556
Steve Block1e0659c2011-05-24 12:43:12 +01003557// Defined in ast.cc
3558bool IsEqualString(void* first, void* second);
3559bool IsEqualNumber(void* first, void* second);
3560
3561
3562// Validation per 11.1.5 Object Initialiser
3563class ObjectLiteralPropertyChecker {
3564 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003565 ObjectLiteralPropertyChecker(Parser* parser, LanguageMode language_mode) :
Steve Block1e0659c2011-05-24 12:43:12 +01003566 props(&IsEqualString),
3567 elems(&IsEqualNumber),
3568 parser_(parser),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003569 language_mode_(language_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +01003570 }
3571
3572 void CheckProperty(
3573 ObjectLiteral::Property* property,
3574 Scanner::Location loc,
3575 bool* ok);
3576
3577 private:
3578 enum PropertyKind {
3579 kGetAccessor = 0x01,
3580 kSetAccessor = 0x02,
3581 kAccessor = kGetAccessor | kSetAccessor,
3582 kData = 0x04
3583 };
3584
3585 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) {
3586 switch (property->kind()) {
3587 case ObjectLiteral::Property::GETTER:
3588 return kGetAccessor;
3589 case ObjectLiteral::Property::SETTER:
3590 return kSetAccessor;
3591 default:
3592 return kData;
3593 }
3594 }
3595
3596 HashMap props;
3597 HashMap elems;
3598 Parser* parser_;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003599 LanguageMode language_mode_;
Steve Block1e0659c2011-05-24 12:43:12 +01003600};
3601
3602
3603void ObjectLiteralPropertyChecker::CheckProperty(
3604 ObjectLiteral::Property* property,
3605 Scanner::Location loc,
3606 bool* ok) {
3607
3608 ASSERT(property != NULL);
3609
Ben Murdochc7cc0282012-03-05 14:35:55 +00003610 Literal* lit = property->key();
Steve Block1e0659c2011-05-24 12:43:12 +01003611 Handle<Object> handle = lit->handle();
3612
3613 uint32_t hash;
3614 HashMap* map;
3615 void* key;
3616
3617 if (handle->IsSymbol()) {
3618 Handle<String> name(String::cast(*handle));
3619 if (name->AsArrayIndex(&hash)) {
Steve Block44f0eee2011-05-26 01:26:41 +01003620 Handle<Object> key_handle = FACTORY->NewNumberFromUint(hash);
Steve Block1e0659c2011-05-24 12:43:12 +01003621 key = key_handle.location();
3622 map = &elems;
3623 } else {
3624 key = handle.location();
3625 hash = name->Hash();
3626 map = &props;
3627 }
3628 } else if (handle->ToArrayIndex(&hash)) {
3629 key = handle.location();
3630 map = &elems;
3631 } else {
3632 ASSERT(handle->IsNumber());
3633 double num = handle->Number();
3634 char arr[100];
3635 Vector<char> buffer(arr, ARRAY_SIZE(arr));
3636 const char* str = DoubleToCString(num, buffer);
Steve Block44f0eee2011-05-26 01:26:41 +01003637 Handle<String> name = FACTORY->NewStringFromAscii(CStrVector(str));
Steve Block1e0659c2011-05-24 12:43:12 +01003638 key = name.location();
3639 hash = name->Hash();
3640 map = &props;
3641 }
3642
3643 // Lookup property previously defined, if any.
3644 HashMap::Entry* entry = map->Lookup(key, hash, true);
3645 intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
3646 intptr_t curr = GetPropertyKind(property);
3647
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003648 // Duplicate data properties are illegal in strict or extended mode.
3649 if (language_mode_ != CLASSIC_MODE && (curr & prev & kData) != 0) {
Steve Block1e0659c2011-05-24 12:43:12 +01003650 parser_->ReportMessageAt(loc, "strict_duplicate_property",
3651 Vector<const char*>::empty());
3652 *ok = false;
3653 return;
3654 }
3655 // Data property conflicting with an accessor.
3656 if (((curr & kData) && (prev & kAccessor)) ||
3657 ((prev & kData) && (curr & kAccessor))) {
3658 parser_->ReportMessageAt(loc, "accessor_data_property",
3659 Vector<const char*>::empty());
3660 *ok = false;
3661 return;
3662 }
3663 // Two accessors of the same type conflicting
3664 if ((curr & prev & kAccessor) != 0) {
3665 parser_->ReportMessageAt(loc, "accessor_get_set",
3666 Vector<const char*>::empty());
3667 *ok = false;
3668 return;
3669 }
3670
3671 // Update map
3672 entry->value = reinterpret_cast<void*> (prev | curr);
3673 *ok = true;
3674}
3675
Steve Blocka7e24c12009-10-30 11:49:00 +00003676
Leon Clarke4515c472010-02-03 11:58:03 +00003677void Parser::BuildObjectLiteralConstantProperties(
3678 ZoneList<ObjectLiteral::Property*>* properties,
3679 Handle<FixedArray> constant_properties,
3680 bool* is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003681 bool* fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003682 int* depth) {
3683 int position = 0;
3684 // Accumulate the value in local variables and store it at the end.
3685 bool is_simple_acc = true;
3686 int depth_acc = 1;
Steve Block6ded16b2010-05-10 14:33:55 +01003687 uint32_t max_element_index = 0;
3688 uint32_t elements = 0;
Leon Clarke4515c472010-02-03 11:58:03 +00003689 for (int i = 0; i < properties->length(); i++) {
3690 ObjectLiteral::Property* property = properties->at(i);
3691 if (!IsBoilerplateProperty(property)) {
3692 is_simple_acc = false;
3693 continue;
3694 }
3695 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
3696 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3697 depth_acc = m_literal->depth() + 1;
3698 }
3699
3700 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
3701 // value for COMPUTED properties, the real value is filled in at
3702 // runtime. The enumeration order is maintained.
3703 Handle<Object> key = property->key()->handle();
3704 Handle<Object> value = GetBoilerplateValue(property->value());
3705 is_simple_acc = is_simple_acc && !value->IsUndefined();
3706
Steve Block6ded16b2010-05-10 14:33:55 +01003707 // Keep track of the number of elements in the object literal and
3708 // the largest element index. If the largest element index is
3709 // much larger than the number of elements, creating an object
3710 // literal with fast elements will be a waste of space.
3711 uint32_t element_index = 0;
3712 if (key->IsString()
3713 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
3714 && element_index > max_element_index) {
3715 max_element_index = element_index;
3716 elements++;
3717 } else if (key->IsSmi()) {
3718 int key_value = Smi::cast(*key)->value();
3719 if (key_value > 0
3720 && static_cast<uint32_t>(key_value) > max_element_index) {
3721 max_element_index = key_value;
3722 }
3723 elements++;
3724 }
3725
Leon Clarke4515c472010-02-03 11:58:03 +00003726 // Add name, value pair to the fixed array.
3727 constant_properties->set(position++, *key);
3728 constant_properties->set(position++, *value);
3729 }
Steve Block6ded16b2010-05-10 14:33:55 +01003730 *fast_elements =
3731 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
Leon Clarke4515c472010-02-03 11:58:03 +00003732 *is_simple = is_simple_acc;
3733 *depth = depth_acc;
3734}
3735
3736
Ben Murdochbb769b22010-08-11 14:56:33 +01003737ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
3738 bool* ok) {
3739 // Special handling of getter and setter syntax:
3740 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3741 // We have already read the "get" or "set" keyword.
3742 Token::Value next = Next();
Steve Block9fac8402011-05-12 15:51:54 +01003743 bool is_keyword = Token::IsKeyword(next);
3744 if (next == Token::IDENTIFIER || next == Token::NUMBER ||
Steve Block1e0659c2011-05-24 12:43:12 +01003745 next == Token::FUTURE_RESERVED_WORD ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003746 next == Token::FUTURE_STRICT_RESERVED_WORD ||
Steve Block9fac8402011-05-12 15:51:54 +01003747 next == Token::STRING || is_keyword) {
3748 Handle<String> name;
3749 if (is_keyword) {
Steve Block44f0eee2011-05-26 01:26:41 +01003750 name = isolate_->factory()->LookupAsciiSymbol(Token::String(next));
Steve Block9fac8402011-05-12 15:51:54 +01003751 } else {
3752 name = GetSymbol(CHECK_OK);
3753 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003754 FunctionLiteral* value =
3755 ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01003756 false, // reserved words are allowed here
Ben Murdochbb769b22010-08-11 14:56:33 +01003757 RelocInfo::kNoPosition,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003758 FunctionLiteral::ANONYMOUS_EXPRESSION,
Ben Murdochbb769b22010-08-11 14:56:33 +01003759 CHECK_OK);
Ben Murdochc7cc0282012-03-05 14:35:55 +00003760 // Allow any number of parameters for compatibilty with JSC.
Steve Block9fac8402011-05-12 15:51:54 +01003761 // Specification only allows zero parameters for get and one for set.
Ben Murdochbb769b22010-08-11 14:56:33 +01003762 ObjectLiteral::Property* property =
Ben Murdoch8b112d22011-06-08 16:22:53 +01003763 new(zone()) ObjectLiteral::Property(is_getter, value);
Ben Murdochbb769b22010-08-11 14:56:33 +01003764 return property;
3765 } else {
3766 ReportUnexpectedToken(next);
3767 *ok = false;
3768 return NULL;
3769 }
3770}
3771
3772
Steve Blocka7e24c12009-10-30 11:49:00 +00003773Expression* Parser::ParseObjectLiteral(bool* ok) {
3774 // ObjectLiteral ::
3775 // '{' (
Ben Murdochbb769b22010-08-11 14:56:33 +01003776 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3777 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
Steve Blocka7e24c12009-10-30 11:49:00 +00003778 // )*[','] '}'
3779
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003780 ZoneList<ObjectLiteral::Property*>* properties =
Ben Murdoch257744e2011-11-30 15:57:28 +00003781 new(zone()) ZoneList<ObjectLiteral::Property*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003782 int number_of_boilerplate_properties = 0;
Steve Block44f0eee2011-05-26 01:26:41 +01003783 bool has_function = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003784
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003785 ObjectLiteralPropertyChecker checker(this, top_scope_->language_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01003786
Steve Blocka7e24c12009-10-30 11:49:00 +00003787 Expect(Token::LBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003788
Steve Blocka7e24c12009-10-30 11:49:00 +00003789 while (peek() != Token::RBRACE) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003790 if (fni_ != NULL) fni_->Enter();
3791
Steve Blocka7e24c12009-10-30 11:49:00 +00003792 Literal* key = NULL;
Ben Murdochbb769b22010-08-11 14:56:33 +01003793 Token::Value next = peek();
Steve Block1e0659c2011-05-24 12:43:12 +01003794
3795 // Location of the property name token
3796 Scanner::Location loc = scanner().peek_location();
3797
Ben Murdochbb769b22010-08-11 14:56:33 +01003798 switch (next) {
Steve Block1e0659c2011-05-24 12:43:12 +01003799 case Token::FUTURE_RESERVED_WORD:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003800 case Token::FUTURE_STRICT_RESERVED_WORD:
Steve Blocka7e24c12009-10-30 11:49:00 +00003801 case Token::IDENTIFIER: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003802 bool is_getter = false;
3803 bool is_setter = false;
3804 Handle<String> id =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003805 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003806 if (fni_ != NULL) fni_->PushLiteralName(id);
3807
Ben Murdochbb769b22010-08-11 14:56:33 +01003808 if ((is_getter || is_setter) && peek() != Token::COLON) {
Steve Block1e0659c2011-05-24 12:43:12 +01003809 // Update loc to point to the identifier
3810 loc = scanner().peek_location();
Steve Blocka7e24c12009-10-30 11:49:00 +00003811 ObjectLiteral::Property* property =
Ben Murdochbb769b22010-08-11 14:56:33 +01003812 ParseObjectLiteralGetSet(is_getter, CHECK_OK);
3813 if (IsBoilerplateProperty(property)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003814 number_of_boilerplate_properties++;
Ben Murdochbb769b22010-08-11 14:56:33 +01003815 }
Steve Block1e0659c2011-05-24 12:43:12 +01003816 // Validate the property.
3817 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003818 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003819 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003820
3821 if (fni_ != NULL) {
3822 fni_->Infer();
3823 fni_->Leave();
3824 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003825 continue; // restart the while
Steve Blocka7e24c12009-10-30 11:49:00 +00003826 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003827 // Failed to parse as get/set property, so it's just a property
3828 // called "get" or "set".
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003829 key = NewLiteral(id);
Steve Blocka7e24c12009-10-30 11:49:00 +00003830 break;
3831 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003832 case Token::STRING: {
3833 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003834 Handle<String> string = GetSymbol(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003835 if (fni_ != NULL) fni_->PushLiteralName(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003836 uint32_t index;
Iain Merrick75681382010-08-19 15:07:18 +01003837 if (!string.is_null() && string->AsArrayIndex(&index)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003838 key = NewNumberLiteral(index);
Ben Murdochbb769b22010-08-11 14:56:33 +01003839 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00003840 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003841 key = NewLiteral(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003842 break;
3843 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003844 case Token::NUMBER: {
3845 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003846 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01003847 double value = StringToDouble(isolate()->unicode_cache(),
3848 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01003849 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003850 key = NewNumberLiteral(value);
3851 break;
3852 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003853 default:
Ben Murdochbb769b22010-08-11 14:56:33 +01003854 if (Token::IsKeyword(next)) {
3855 Consume(next);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003856 Handle<String> string = GetSymbol(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003857 key = NewLiteral(string);
Ben Murdochbb769b22010-08-11 14:56:33 +01003858 } else {
3859 // Unexpected token.
3860 Token::Value next = Next();
3861 ReportUnexpectedToken(next);
3862 *ok = false;
3863 return NULL;
3864 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003865 }
3866
3867 Expect(Token::COLON, CHECK_OK);
3868 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
3869
3870 ObjectLiteral::Property* property =
Ben Murdoch8b112d22011-06-08 16:22:53 +01003871 new(zone()) ObjectLiteral::Property(key, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003872
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003873 // Mark top-level object literals that contain function literals and
3874 // pretenure the literal so it can be added as a constant function
3875 // property.
3876 if (top_scope_->DeclarationScope()->is_global_scope() &&
3877 value->AsFunctionLiteral() != NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +01003878 has_function = true;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003879 value->AsFunctionLiteral()->set_pretenure();
Steve Block44f0eee2011-05-26 01:26:41 +01003880 }
3881
Steve Blocka7e24c12009-10-30 11:49:00 +00003882 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3883 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
Steve Block1e0659c2011-05-24 12:43:12 +01003884 // Validate the property
3885 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003886 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003887
3888 // TODO(1240767): Consider allowing trailing comma.
3889 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003890
3891 if (fni_ != NULL) {
3892 fni_->Infer();
3893 fni_->Leave();
3894 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003895 }
3896 Expect(Token::RBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003897
Steve Blocka7e24c12009-10-30 11:49:00 +00003898 // Computation of literal_index must happen before pre parse bailout.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003899 int literal_index = current_function_state_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003900
Steve Block44f0eee2011-05-26 01:26:41 +01003901 Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray(
3902 number_of_boilerplate_properties * 2, TENURED);
Leon Clarke4515c472010-02-03 11:58:03 +00003903
Steve Blocka7e24c12009-10-30 11:49:00 +00003904 bool is_simple = true;
Steve Block6ded16b2010-05-10 14:33:55 +01003905 bool fast_elements = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003906 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003907 BuildObjectLiteralConstantProperties(properties,
Leon Clarke4515c472010-02-03 11:58:03 +00003908 constant_properties,
3909 &is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003910 &fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003911 &depth);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003912 return new(zone()) ObjectLiteral(isolate(),
3913 constant_properties,
3914 properties,
3915 literal_index,
3916 is_simple,
3917 fast_elements,
3918 depth,
3919 has_function);
Steve Blocka7e24c12009-10-30 11:49:00 +00003920}
3921
3922
3923Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003924 if (!scanner().ScanRegExpPattern(seen_equal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003925 Next();
3926 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3927 *ok = false;
3928 return NULL;
3929 }
3930
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003931 int literal_index = current_function_state_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003932
Steve Block9fac8402011-05-12 15:51:54 +01003933 Handle<String> js_pattern = NextLiteralString(TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003934 scanner().ScanRegExpFlags();
Steve Block9fac8402011-05-12 15:51:54 +01003935 Handle<String> js_flags = NextLiteralString(TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003936 Next();
3937
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003938 return new(zone()) RegExpLiteral(
3939 isolate(), js_pattern, js_flags, literal_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003940}
3941
3942
3943ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3944 // Arguments ::
3945 // '(' (AssignmentExpression)*[','] ')'
3946
Ben Murdoch257744e2011-11-30 15:57:28 +00003947 ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003948 Expect(Token::LPAREN, CHECK_OK);
3949 bool done = (peek() == Token::RPAREN);
3950 while (!done) {
3951 Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003952 result->Add(argument);
Steve Block053d10c2011-06-13 19:13:29 +01003953 if (result->length() > kMaxNumFunctionParameters) {
3954 ReportMessageAt(scanner().location(), "too_many_arguments",
3955 Vector<const char*>::empty());
3956 *ok = false;
3957 return NULL;
3958 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003959 done = (peek() == Token::RPAREN);
3960 if (!done) Expect(Token::COMMA, CHECK_OK);
3961 }
3962 Expect(Token::RPAREN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003963 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003964}
3965
3966
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003967class SingletonLogger : public ParserRecorder {
3968 public:
3969 SingletonLogger() : has_error_(false), start_(-1), end_(-1) { }
3970 ~SingletonLogger() { }
3971
3972 void Reset() { has_error_ = false; }
3973
3974 virtual void LogFunction(int start,
3975 int end,
3976 int literals,
3977 int properties,
3978 LanguageMode mode) {
3979 ASSERT(!has_error_);
3980 start_ = start;
3981 end_ = end;
3982 literals_ = literals;
3983 properties_ = properties;
3984 mode_ = mode;
3985 };
3986
3987 // Logs a symbol creation of a literal or identifier.
3988 virtual void LogAsciiSymbol(int start, Vector<const char> literal) { }
3989 virtual void LogUC16Symbol(int start, Vector<const uc16> literal) { }
3990
3991 // Logs an error message and marks the log as containing an error.
3992 // Further logging will be ignored, and ExtractData will return a vector
3993 // representing the error only.
3994 virtual void LogMessage(int start,
3995 int end,
3996 const char* message,
3997 const char* argument_opt) {
3998 has_error_ = true;
3999 start_ = start;
4000 end_ = end;
4001 message_ = message;
4002 argument_opt_ = argument_opt;
4003 }
4004
4005 virtual int function_position() { return 0; }
4006
4007 virtual int symbol_position() { return 0; }
4008
4009 virtual int symbol_ids() { return -1; }
4010
4011 virtual Vector<unsigned> ExtractData() {
4012 UNREACHABLE();
4013 return Vector<unsigned>();
4014 }
4015
4016 virtual void PauseRecording() { }
4017
4018 virtual void ResumeRecording() { }
4019
4020 bool has_error() { return has_error_; }
4021
4022 int start() { return start_; }
4023 int end() { return end_; }
4024 int literals() {
4025 ASSERT(!has_error_);
4026 return literals_;
4027 }
4028 int properties() {
4029 ASSERT(!has_error_);
4030 return properties_;
4031 }
4032 LanguageMode language_mode() {
4033 ASSERT(!has_error_);
4034 return mode_;
4035 }
4036 const char* message() {
4037 ASSERT(has_error_);
4038 return message_;
4039 }
4040 const char* argument_opt() {
4041 ASSERT(has_error_);
4042 return argument_opt_;
4043 }
4044
4045 private:
4046 bool has_error_;
4047 int start_;
4048 int end_;
4049 // For function entries.
4050 int literals_;
4051 int properties_;
4052 LanguageMode mode_;
4053 // For error messages.
4054 const char* message_;
4055 const char* argument_opt_;
4056};
4057
4058
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004059FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
4060 bool name_is_strict_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00004061 int function_token_position,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004062 FunctionLiteral::Type type,
Steve Blocka7e24c12009-10-30 11:49:00 +00004063 bool* ok) {
4064 // Function ::
4065 // '(' FormalParameterList? ')' '{' FunctionBody '}'
Steve Blocka7e24c12009-10-30 11:49:00 +00004066
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004067 // Anonymous functions were passed either the empty symbol or a null
4068 // handle as the function name. Remember if we were passed a non-empty
4069 // handle to decide whether to invoke function name inference.
4070 bool should_infer_name = function_name.is_null();
4071
4072 // We want a non-null handle as the function name.
4073 if (should_infer_name) {
4074 function_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00004075 }
4076
4077 int num_parameters = 0;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004078 // Function declarations are function scoped in normal mode, so they are
4079 // hoisted. In harmony block scoping mode they are block scoped, so they
4080 // are not hoisted.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004081 Scope* scope = (type == FunctionLiteral::DECLARATION && !is_extended_mode())
4082 ? NewScope(top_scope_->DeclarationScope(), FUNCTION_SCOPE)
4083 : NewScope(top_scope_, FUNCTION_SCOPE);
4084 ZoneList<Statement*>* body = NULL;
4085 int materialized_literal_count = -1;
4086 int expected_property_count = -1;
4087 int handler_count = 0;
Ben Murdoch8b112d22011-06-08 16:22:53 +01004088 bool only_simple_this_property_assignments;
4089 Handle<FixedArray> this_property_assignments;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004090 bool has_duplicate_parameters = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00004091 // Parse function body.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004092 { FunctionState function_state(this, scope, isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004093 top_scope_->SetScopeName(function_name);
Steve Blocka7e24c12009-10-30 11:49:00 +00004094
4095 // FormalParameterList ::
4096 // '(' (Identifier)*[','] ')'
4097 Expect(Token::LPAREN, CHECK_OK);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004098 scope->set_start_position(scanner().location().beg_pos);
Ben Murdoch257744e2011-11-30 15:57:28 +00004099 Scanner::Location name_loc = Scanner::Location::invalid();
4100 Scanner::Location dupe_loc = Scanner::Location::invalid();
4101 Scanner::Location reserved_loc = Scanner::Location::invalid();
Steve Block1e0659c2011-05-24 12:43:12 +01004102
Steve Blocka7e24c12009-10-30 11:49:00 +00004103 bool done = (peek() == Token::RPAREN);
4104 while (!done) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004105 bool is_strict_reserved = false;
Steve Block1e0659c2011-05-24 12:43:12 +01004106 Handle<String> param_name =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004107 ParseIdentifierOrStrictReservedWord(&is_strict_reserved,
4108 CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01004109
4110 // Store locations for possible future error reports.
4111 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
4112 name_loc = scanner().location();
4113 }
4114 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004115 has_duplicate_parameters = true;
Steve Block1e0659c2011-05-24 12:43:12 +01004116 dupe_loc = scanner().location();
4117 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004118 if (!reserved_loc.IsValid() && is_strict_reserved) {
Steve Block1e0659c2011-05-24 12:43:12 +01004119 reserved_loc = scanner().location();
4120 }
4121
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004122 top_scope_->DeclareParameter(param_name, is_extended_mode() ? LET : VAR);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004123 num_parameters++;
Steve Block1e0659c2011-05-24 12:43:12 +01004124 if (num_parameters > kMaxNumFunctionParameters) {
4125 ReportMessageAt(scanner().location(), "too_many_parameters",
4126 Vector<const char*>::empty());
4127 *ok = false;
4128 return NULL;
4129 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004130 done = (peek() == Token::RPAREN);
4131 if (!done) Expect(Token::COMMA, CHECK_OK);
4132 }
4133 Expect(Token::RPAREN, CHECK_OK);
4134
4135 Expect(Token::LBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00004136
4137 // If we have a named function expression, we add a local variable
4138 // declaration to the body of the function with the name of the
4139 // function and let it refer to the function itself (closure).
4140 // NOTE: We create a proxy and resolve it here so that in the
4141 // future we can change the AST to only refer to VariableProxies
4142 // instead of Variables and Proxis as is the case now.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004143 Variable* fvar = NULL;
4144 Token::Value fvar_init_op = Token::INIT_CONST;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004145 if (type == FunctionLiteral::NAMED_EXPRESSION) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004146 VariableMode fvar_mode;
4147 if (is_extended_mode()) {
4148 fvar_mode = CONST_HARMONY;
4149 fvar_init_op = Token::INIT_CONST_HARMONY;
4150 } else {
4151 fvar_mode = CONST;
4152 }
4153 fvar = top_scope_->DeclareFunctionVar(function_name, fvar_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00004154 }
4155
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004156 // Determine whether the function will be lazily compiled.
4157 // The heuristics are:
4158 // - It must not have been prohibited by the caller to Parse (some callers
4159 // need a full AST).
4160 // - The outer scope must be trivial (only global variables in scope).
4161 // - The function mustn't be a function expression with an open parenthesis
4162 // before; we consider that a hint that the function will be called
4163 // immediately, and it would be a waste of time to make it lazily
4164 // compiled.
4165 // These are all things we can know at this point, without looking at the
4166 // function itself.
Ben Murdochb8e0da22011-05-16 14:20:40 +01004167 bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
4168 top_scope_->outer_scope()->is_global_scope() &&
4169 top_scope_->HasTrivialOuterContext() &&
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004170 !parenthesized_function_);
Ben Murdochb8e0da22011-05-16 14:20:40 +01004171 parenthesized_function_ = false; // The bit was set for this function only.
Steve Blocka7e24c12009-10-30 11:49:00 +00004172
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004173 if (is_lazily_compiled) {
4174 int function_block_pos = scanner().location().beg_pos;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004175 FunctionEntry entry;
4176 if (pre_data_ != NULL) {
4177 // If we have pre_data_, we use it to skip parsing the function body.
4178 // the preparser data contains the information we need to construct the
4179 // lazy function.
4180 entry = pre_data()->GetFunctionEntry(function_block_pos);
4181 if (entry.is_valid()) {
4182 if (entry.end_pos() <= function_block_pos) {
4183 // End position greater than end of stream is safe, and hard
4184 // to check.
4185 ReportInvalidPreparseData(function_name, CHECK_OK);
4186 }
4187 scanner().SeekForward(entry.end_pos() - 1);
4188
4189 scope->set_end_position(entry.end_pos());
4190 Expect(Token::RBRACE, CHECK_OK);
4191 isolate()->counters()->total_preparse_skipped()->Increment(
4192 scope->end_position() - function_block_pos);
4193 materialized_literal_count = entry.literal_count();
4194 expected_property_count = entry.property_count();
4195 top_scope_->SetLanguageMode(entry.language_mode());
4196 only_simple_this_property_assignments = false;
4197 this_property_assignments = isolate()->factory()->empty_fixed_array();
4198 } else {
4199 is_lazily_compiled = false;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004200 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004201 } else {
4202 // With no preparser data, we partially parse the function, without
4203 // building an AST. This gathers the data needed to build a lazy
4204 // function.
4205 SingletonLogger logger;
4206 preparser::PreParser::PreParseResult result =
4207 LazyParseFunctionLiteral(&logger);
4208 if (result == preparser::PreParser::kPreParseStackOverflow) {
4209 // Propagate stack overflow.
4210 stack_overflow_ = true;
4211 *ok = false;
4212 return NULL;
4213 }
4214 if (logger.has_error()) {
4215 const char* arg = logger.argument_opt();
4216 Vector<const char*> args;
4217 if (arg != NULL) {
4218 args = Vector<const char*>(&arg, 1);
4219 }
4220 ReportMessageAt(Scanner::Location(logger.start(), logger.end()),
4221 logger.message(), args);
4222 *ok = false;
4223 return NULL;
4224 }
4225 scope->set_end_position(logger.end());
4226 Expect(Token::RBRACE, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004227 isolate()->counters()->total_preparse_skipped()->Increment(
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004228 scope->end_position() - function_block_pos);
4229 materialized_literal_count = logger.literals();
4230 expected_property_count = logger.properties();
4231 top_scope_->SetLanguageMode(logger.language_mode());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004232 only_simple_this_property_assignments = false;
4233 this_property_assignments = isolate()->factory()->empty_fixed_array();
Leon Clarkeac952652010-07-15 11:15:24 +01004234 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004235 }
4236
4237 if (!is_lazily_compiled) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004238 body = new(zone()) ZoneList<Statement*>(8);
4239 if (fvar != NULL) {
4240 VariableProxy* fproxy = top_scope_->NewUnresolved(function_name);
4241 fproxy->BindTo(fvar);
4242 body->Add(new(zone()) ExpressionStatement(
4243 new(zone()) Assignment(isolate(),
4244 fvar_init_op,
4245 fproxy,
4246 new(zone()) ThisFunction(isolate()),
4247 RelocInfo::kNoPosition)));
4248 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004249 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
4250
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004251 materialized_literal_count = function_state.materialized_literal_count();
4252 expected_property_count = function_state.expected_property_count();
4253 handler_count = function_state.handler_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00004254 only_simple_this_property_assignments =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004255 function_state.only_simple_this_property_assignments();
4256 this_property_assignments = function_state.this_property_assignments();
Steve Blocka7e24c12009-10-30 11:49:00 +00004257
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004258 Expect(Token::RBRACE, CHECK_OK);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004259 scope->set_end_position(scanner().location().end_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00004260 }
4261
Steve Block1e0659c2011-05-24 12:43:12 +01004262 // Validate strict mode.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004263 if (!top_scope_->is_classic_mode()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004264 if (IsEvalOrArguments(function_name)) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004265 int start_pos = scope->start_position();
Steve Block1e0659c2011-05-24 12:43:12 +01004266 int position = function_token_position != RelocInfo::kNoPosition
4267 ? function_token_position
4268 : (start_pos > 0 ? start_pos - 1 : start_pos);
4269 Scanner::Location location = Scanner::Location(position, start_pos);
4270 ReportMessageAt(location,
4271 "strict_function_name", Vector<const char*>::empty());
4272 *ok = false;
4273 return NULL;
4274 }
4275 if (name_loc.IsValid()) {
4276 ReportMessageAt(name_loc, "strict_param_name",
4277 Vector<const char*>::empty());
4278 *ok = false;
4279 return NULL;
4280 }
4281 if (dupe_loc.IsValid()) {
4282 ReportMessageAt(dupe_loc, "strict_param_dupe",
4283 Vector<const char*>::empty());
4284 *ok = false;
4285 return NULL;
4286 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004287 if (name_is_strict_reserved) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004288 int start_pos = scope->start_position();
Steve Block1e0659c2011-05-24 12:43:12 +01004289 int position = function_token_position != RelocInfo::kNoPosition
4290 ? function_token_position
4291 : (start_pos > 0 ? start_pos - 1 : start_pos);
4292 Scanner::Location location = Scanner::Location(position, start_pos);
4293 ReportMessageAt(location, "strict_reserved_word",
4294 Vector<const char*>::empty());
4295 *ok = false;
4296 return NULL;
4297 }
4298 if (reserved_loc.IsValid()) {
4299 ReportMessageAt(reserved_loc, "strict_reserved_word",
4300 Vector<const char*>::empty());
4301 *ok = false;
4302 return NULL;
4303 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004304 CheckOctalLiteral(scope->start_position(),
4305 scope->end_position(),
4306 CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01004307 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004308 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01004309
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004310 if (is_extended_mode()) {
Ben Murdoch589d6972011-11-30 16:04:58 +00004311 CheckConflictingVarDeclarations(scope, CHECK_OK);
4312 }
4313
Ben Murdoch8b112d22011-06-08 16:22:53 +01004314 FunctionLiteral* function_literal =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004315 new(zone()) FunctionLiteral(isolate(),
4316 function_name,
Ben Murdoch8b112d22011-06-08 16:22:53 +01004317 scope,
4318 body,
4319 materialized_literal_count,
4320 expected_property_count,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004321 handler_count,
Ben Murdoch8b112d22011-06-08 16:22:53 +01004322 only_simple_this_property_assignments,
4323 this_property_assignments,
4324 num_parameters,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004325 type,
4326 has_duplicate_parameters);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004327 function_literal->set_function_token_position(function_token_position);
4328
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004329 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004330 return function_literal;
Steve Blocka7e24c12009-10-30 11:49:00 +00004331}
4332
4333
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004334preparser::PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
4335 SingletonLogger* logger) {
4336 HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse());
4337 ASSERT_EQ(Token::LBRACE, scanner().current_token());
4338
4339 if (reusable_preparser_ == NULL) {
4340 intptr_t stack_limit = isolate()->stack_guard()->real_climit();
4341 bool do_allow_lazy = true;
4342 reusable_preparser_ = new preparser::PreParser(&scanner_,
4343 NULL,
4344 stack_limit,
4345 do_allow_lazy,
4346 allow_natives_syntax_);
4347 }
4348 preparser::PreParser::PreParseResult result =
4349 reusable_preparser_->PreParseLazyFunction(top_scope_->language_mode(),
4350 logger);
4351 return result;
4352}
4353
4354
Steve Blocka7e24c12009-10-30 11:49:00 +00004355Expression* Parser::ParseV8Intrinsic(bool* ok) {
4356 // CallRuntime ::
4357 // '%' Identifier Arguments
4358
4359 Expect(Token::MOD, CHECK_OK);
4360 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00004361 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004362
4363 if (extension_ != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004364 // The extension structures are only accessible while parsing the
4365 // very first time not when reparsing because of lazy compilation.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004366 top_scope_->DeclarationScope()->ForceEagerCompilation();
Steve Blocka7e24c12009-10-30 11:49:00 +00004367 }
4368
Steve Block44f0eee2011-05-26 01:26:41 +01004369 const Runtime::Function* function = Runtime::FunctionForSymbol(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00004370
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004371 // Check for built-in IS_VAR macro.
4372 if (function != NULL &&
4373 function->intrinsic_type == Runtime::RUNTIME &&
4374 function->function_id == Runtime::kIS_VAR) {
4375 // %IS_VAR(x) evaluates to x if x is a variable,
4376 // leads to a parse error otherwise. Could be implemented as an
4377 // inline function %_IS_VAR(x) to eliminate this special case.
4378 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
4379 return args->at(0);
4380 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00004381 ReportMessage("unable_to_parse", Vector<const char*>::empty());
Steve Block6ded16b2010-05-10 14:33:55 +01004382 *ok = false;
4383 return NULL;
Steve Block6ded16b2010-05-10 14:33:55 +01004384 }
4385 }
4386
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004387 // Check that the expected number of arguments are being passed.
4388 if (function != NULL &&
4389 function->nargs != -1 &&
4390 function->nargs != args->length()) {
4391 ReportMessage("illegal_access", Vector<const char*>::empty());
4392 *ok = false;
4393 return NULL;
4394 }
4395
4396 // We have a valid intrinsics call or a call to a builtin.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004397 return new(zone()) CallRuntime(isolate(), name, function, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00004398}
4399
4400
Steve Block1e0659c2011-05-24 12:43:12 +01004401bool Parser::peek_any_identifier() {
4402 Token::Value next = peek();
4403 return next == Token::IDENTIFIER ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004404 next == Token::FUTURE_RESERVED_WORD ||
4405 next == Token::FUTURE_STRICT_RESERVED_WORD;
Steve Block1e0659c2011-05-24 12:43:12 +01004406}
4407
4408
Steve Blocka7e24c12009-10-30 11:49:00 +00004409void Parser::Consume(Token::Value token) {
4410 Token::Value next = Next();
4411 USE(next);
4412 USE(token);
4413 ASSERT(next == token);
4414}
4415
4416
4417void Parser::Expect(Token::Value token, bool* ok) {
4418 Token::Value next = Next();
4419 if (next == token) return;
4420 ReportUnexpectedToken(next);
4421 *ok = false;
4422}
4423
4424
Leon Clarke4515c472010-02-03 11:58:03 +00004425bool Parser::Check(Token::Value token) {
4426 Token::Value next = peek();
4427 if (next == token) {
4428 Consume(next);
4429 return true;
4430 }
4431 return false;
4432}
4433
4434
Steve Blocka7e24c12009-10-30 11:49:00 +00004435void Parser::ExpectSemicolon(bool* ok) {
4436 // Check for automatic semicolon insertion according to
4437 // the rules given in ECMA-262, section 7.9, page 21.
4438 Token::Value tok = peek();
4439 if (tok == Token::SEMICOLON) {
4440 Next();
4441 return;
4442 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004443 if (scanner().HasAnyLineTerminatorBeforeNext() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00004444 tok == Token::RBRACE ||
4445 tok == Token::EOS) {
4446 return;
4447 }
4448 Expect(Token::SEMICOLON, ok);
4449}
4450
4451
4452Literal* Parser::GetLiteralUndefined() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004453 return NewLiteral(isolate()->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00004454}
4455
4456
4457Literal* Parser::GetLiteralTheHole() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004458 return NewLiteral(isolate()->factory()->the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00004459}
4460
4461
4462Literal* Parser::GetLiteralNumber(double value) {
4463 return NewNumberLiteral(value);
4464}
4465
4466
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004467// Parses an identifier that is valid for the current scope, in particular it
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004468// fails on strict mode future reserved keywords in a strict scope.
Steve Blocka7e24c12009-10-30 11:49:00 +00004469Handle<String> Parser::ParseIdentifier(bool* ok) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004470 if (!top_scope_->is_classic_mode()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004471 Expect(Token::IDENTIFIER, ok);
4472 } else if (!Check(Token::IDENTIFIER)) {
4473 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
4474 }
4475 if (!*ok) return Handle<String>();
4476 return GetSymbol(ok);
Steve Block1e0659c2011-05-24 12:43:12 +01004477}
4478
4479
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004480// Parses and identifier or a strict mode future reserved word, and indicate
4481// whether it is strict mode future reserved.
4482Handle<String> Parser::ParseIdentifierOrStrictReservedWord(
4483 bool* is_strict_reserved, bool* ok) {
4484 *is_strict_reserved = false;
4485 if (!Check(Token::IDENTIFIER)) {
4486 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
4487 *is_strict_reserved = true;
Steve Block1e0659c2011-05-24 12:43:12 +01004488 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004489 if (!*ok) return Handle<String>();
Iain Merrick9ac36c92010-09-13 15:29:50 +01004490 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00004491}
4492
Ben Murdochbb769b22010-08-11 14:56:33 +01004493
4494Handle<String> Parser::ParseIdentifierName(bool* ok) {
4495 Token::Value next = Next();
Steve Block1e0659c2011-05-24 12:43:12 +01004496 if (next != Token::IDENTIFIER &&
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004497 next != Token::FUTURE_RESERVED_WORD &&
4498 next != Token::FUTURE_STRICT_RESERVED_WORD &&
4499 !Token::IsKeyword(next)) {
Ben Murdochbb769b22010-08-11 14:56:33 +01004500 ReportUnexpectedToken(next);
4501 *ok = false;
4502 return Handle<String>();
4503 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01004504 return GetSymbol(ok);
Ben Murdochbb769b22010-08-11 14:56:33 +01004505}
4506
4507
Ben Murdochc7cc0282012-03-05 14:35:55 +00004508void Parser::MarkAsLValue(Expression* expression) {
4509 VariableProxy* proxy = expression != NULL
4510 ? expression->AsVariableProxy()
4511 : NULL;
4512
4513 if (proxy != NULL) proxy->MarkAsLValue();
4514}
4515
4516
Steve Block1e0659c2011-05-24 12:43:12 +01004517// Checks LHS expression for assignment and prefix/postfix increment/decrement
4518// in strict mode.
4519void Parser::CheckStrictModeLValue(Expression* expression,
4520 const char* error,
4521 bool* ok) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00004522 ASSERT(!top_scope_->is_classic_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01004523 VariableProxy* lhs = expression != NULL
4524 ? expression->AsVariableProxy()
4525 : NULL;
4526
4527 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
4528 ReportMessage(error, Vector<const char*>::empty());
4529 *ok = false;
4530 }
4531}
4532
4533
Ben Murdoch257744e2011-11-30 15:57:28 +00004534// Checks whether an octal literal was last seen between beg_pos and end_pos.
4535// If so, reports an error. Only called for strict mode.
Steve Block1e0659c2011-05-24 12:43:12 +01004536void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
Ben Murdoch257744e2011-11-30 15:57:28 +00004537 Scanner::Location octal = scanner().octal_position();
4538 if (octal.IsValid() &&
4539 beg_pos <= octal.beg_pos &&
4540 octal.end_pos <= end_pos) {
4541 ReportMessageAt(octal, "strict_octal_literal",
Steve Block1e0659c2011-05-24 12:43:12 +01004542 Vector<const char*>::empty());
4543 scanner().clear_octal_position();
4544 *ok = false;
4545 }
4546}
4547
4548
Ben Murdoch589d6972011-11-30 16:04:58 +00004549void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
4550 Declaration* decl = scope->CheckConflictingVarDeclarations();
4551 if (decl != NULL) {
4552 // In harmony mode we treat conflicting variable bindinds as early
4553 // errors. See ES5 16 for a definition of early errors.
4554 Handle<String> name = decl->proxy()->name();
4555 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
4556 const char* elms[2] = { "Variable", *c_string };
4557 Vector<const char*> args(elms, 2);
4558 int position = decl->proxy()->position();
4559 Scanner::Location location = position == RelocInfo::kNoPosition
4560 ? Scanner::Location::invalid()
4561 : Scanner::Location(position, position + 1);
4562 ReportMessageAt(location, "redeclaration", args);
4563 *ok = false;
4564 }
4565}
4566
4567
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004568// This function reads an identifier name and determines whether or not it
Steve Block1e0659c2011-05-24 12:43:12 +01004569// is 'get' or 'set'.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004570Handle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get,
4571 bool* is_set,
4572 bool* ok) {
4573 Handle<String> result = ParseIdentifierName(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00004574 if (!*ok) return Handle<String>();
Steve Block9fac8402011-05-12 15:51:54 +01004575 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
4576 const char* token = scanner().literal_ascii_string().start();
4577 *is_get = strncmp(token, "get", 3) == 0;
4578 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00004579 }
Steve Block1e0659c2011-05-24 12:43:12 +01004580 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00004581}
4582
4583
4584// ----------------------------------------------------------------------------
4585// Parser support
4586
4587
4588bool Parser::TargetStackContainsLabel(Handle<String> label) {
4589 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4590 BreakableStatement* stat = t->node()->AsBreakableStatement();
4591 if (stat != NULL && ContainsLabel(stat->labels(), label))
4592 return true;
4593 }
4594 return false;
4595}
4596
4597
4598BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
4599 bool anonymous = label.is_null();
4600 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4601 BreakableStatement* stat = t->node()->AsBreakableStatement();
4602 if (stat == NULL) continue;
4603 if ((anonymous && stat->is_target_for_anonymous()) ||
4604 (!anonymous && ContainsLabel(stat->labels(), label))) {
4605 RegisterTargetUse(stat->break_target(), t->previous());
4606 return stat;
4607 }
4608 }
4609 return NULL;
4610}
4611
4612
4613IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
4614 bool* ok) {
4615 bool anonymous = label.is_null();
4616 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4617 IterationStatement* stat = t->node()->AsIterationStatement();
4618 if (stat == NULL) continue;
4619
4620 ASSERT(stat->is_target_for_anonymous());
4621 if (anonymous || ContainsLabel(stat->labels(), label)) {
4622 RegisterTargetUse(stat->continue_target(), t->previous());
4623 return stat;
4624 }
4625 }
4626 return NULL;
4627}
4628
4629
Ben Murdoch8b112d22011-06-08 16:22:53 +01004630void Parser::RegisterTargetUse(Label* target, Target* stop) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004631 // Register that a break target found at the given stop in the
4632 // target stack has been used from the top of the target stack. Add
4633 // the break target to any TargetCollectors passed on the stack.
4634 for (Target* t = target_stack_; t != stop; t = t->previous()) {
4635 TargetCollector* collector = t->node()->AsTargetCollector();
4636 if (collector != NULL) collector->AddTarget(target);
4637 }
4638}
4639
4640
4641Literal* Parser::NewNumberLiteral(double number) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004642 return NewLiteral(isolate()->factory()->NewNumber(number, TENURED));
Steve Blocka7e24c12009-10-30 11:49:00 +00004643}
4644
4645
4646Expression* Parser::NewThrowReferenceError(Handle<String> type) {
Steve Block44f0eee2011-05-26 01:26:41 +01004647 return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00004648 type, HandleVector<Object>(NULL, 0));
4649}
4650
4651
4652Expression* Parser::NewThrowSyntaxError(Handle<String> type,
4653 Handle<Object> first) {
4654 int argc = first.is_null() ? 0 : 1;
4655 Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
Steve Block44f0eee2011-05-26 01:26:41 +01004656 return NewThrowError(
4657 isolate()->factory()->MakeSyntaxError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00004658}
4659
4660
4661Expression* Parser::NewThrowTypeError(Handle<String> type,
4662 Handle<Object> first,
4663 Handle<Object> second) {
4664 ASSERT(!first.is_null() && !second.is_null());
4665 Handle<Object> elements[] = { first, second };
4666 Vector< Handle<Object> > arguments =
4667 HandleVector<Object>(elements, ARRAY_SIZE(elements));
Steve Block44f0eee2011-05-26 01:26:41 +01004668 return NewThrowError(
4669 isolate()->factory()->MakeTypeError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00004670}
4671
4672
4673Expression* Parser::NewThrowError(Handle<String> constructor,
4674 Handle<String> type,
4675 Vector< Handle<Object> > arguments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004676 int argc = arguments.length();
Steve Block44f0eee2011-05-26 01:26:41 +01004677 Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc,
4678 TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004679 for (int i = 0; i < argc; i++) {
4680 Handle<Object> element = arguments[i];
4681 if (!element.is_null()) {
Steve Block1e0659c2011-05-24 12:43:12 +01004682 elements->set(i, *element);
Steve Blocka7e24c12009-10-30 11:49:00 +00004683 }
4684 }
Steve Block44f0eee2011-05-26 01:26:41 +01004685 Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(elements,
4686 TENURED);
Steve Block1e0659c2011-05-24 12:43:12 +01004687
Ben Murdoch257744e2011-11-30 15:57:28 +00004688 ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004689 args->Add(NewLiteral(type));
4690 args->Add(NewLiteral(array));
4691 CallRuntime* call_constructor = new(zone()) CallRuntime(isolate(),
4692 constructor,
4693 NULL,
4694 args);
4695 return new(zone()) Throw(isolate(),
4696 call_constructor,
4697 scanner().location().beg_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00004698}
4699
Leon Clarke4515c472010-02-03 11:58:03 +00004700// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +00004701// Regular expressions
4702
4703
4704RegExpParser::RegExpParser(FlatStringReader* in,
4705 Handle<String>* error,
4706 bool multiline)
Steve Block44f0eee2011-05-26 01:26:41 +01004707 : isolate_(Isolate::Current()),
4708 error_(error),
4709 captures_(NULL),
4710 in_(in),
4711 current_(kEndMarker),
4712 next_pos_(0),
4713 capture_count_(0),
4714 has_more_(true),
4715 multiline_(multiline),
4716 simple_(false),
4717 contains_anchor_(false),
4718 is_scanned_for_captures_(false),
4719 failed_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004720 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004721}
4722
4723
4724uc32 RegExpParser::Next() {
4725 if (has_next()) {
4726 return in()->Get(next_pos_);
4727 } else {
4728 return kEndMarker;
4729 }
4730}
4731
4732
4733void RegExpParser::Advance() {
4734 if (next_pos_ < in()->length()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004735 StackLimitCheck check(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004736 if (check.HasOverflowed()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004737 ReportError(CStrVector(Isolate::kStackOverflowMessage));
4738 } else if (isolate()->zone()->excess_allocation()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004739 ReportError(CStrVector("Regular expression too large"));
4740 } else {
4741 current_ = in()->Get(next_pos_);
4742 next_pos_++;
4743 }
4744 } else {
4745 current_ = kEndMarker;
4746 has_more_ = false;
4747 }
4748}
4749
4750
4751void RegExpParser::Reset(int pos) {
4752 next_pos_ = pos;
4753 Advance();
4754}
4755
4756
4757void RegExpParser::Advance(int dist) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004758 next_pos_ += dist - 1;
4759 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004760}
4761
4762
4763bool RegExpParser::simple() {
4764 return simple_;
4765}
4766
4767RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
4768 failed_ = true;
Steve Block44f0eee2011-05-26 01:26:41 +01004769 *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004770 // Zip to the end to make sure the no more input is read.
4771 current_ = kEndMarker;
4772 next_pos_ = in()->length();
4773 return NULL;
4774}
4775
4776
4777// Pattern ::
4778// Disjunction
4779RegExpTree* RegExpParser::ParsePattern() {
4780 RegExpTree* result = ParseDisjunction(CHECK_FAILED);
4781 ASSERT(!has_more());
4782 // If the result of parsing is a literal string atom, and it has the
4783 // same length as the input, then the atom is identical to the input.
4784 if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
4785 simple_ = true;
4786 }
4787 return result;
4788}
4789
4790
4791// Disjunction ::
4792// Alternative
4793// Alternative | Disjunction
4794// Alternative ::
4795// [empty]
4796// Term Alternative
4797// Term ::
4798// Assertion
4799// Atom
4800// Atom Quantifier
4801RegExpTree* RegExpParser::ParseDisjunction() {
4802 // Used to store current state while parsing subexpressions.
4803 RegExpParserState initial_state(NULL, INITIAL, 0);
4804 RegExpParserState* stored_state = &initial_state;
4805 // Cache the builder in a local variable for quick access.
4806 RegExpBuilder* builder = initial_state.builder();
4807 while (true) {
4808 switch (current()) {
4809 case kEndMarker:
4810 if (stored_state->IsSubexpression()) {
4811 // Inside a parenthesized group when hitting end of input.
4812 ReportError(CStrVector("Unterminated group") CHECK_FAILED);
4813 }
4814 ASSERT_EQ(INITIAL, stored_state->group_type());
4815 // Parsing completed successfully.
4816 return builder->ToRegExp();
4817 case ')': {
4818 if (!stored_state->IsSubexpression()) {
4819 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
4820 }
4821 ASSERT_NE(INITIAL, stored_state->group_type());
4822
4823 Advance();
4824 // End disjunction parsing and convert builder content to new single
4825 // regexp atom.
4826 RegExpTree* body = builder->ToRegExp();
4827
4828 int end_capture_index = captures_started();
4829
4830 int capture_index = stored_state->capture_index();
4831 SubexpressionType type = stored_state->group_type();
4832
4833 // Restore previous state.
4834 stored_state = stored_state->previous_state();
4835 builder = stored_state->builder();
4836
4837 // Build result of subexpression.
4838 if (type == CAPTURE) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01004839 RegExpCapture* capture = new(zone()) RegExpCapture(body, capture_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00004840 captures_->at(capture_index - 1) = capture;
4841 body = capture;
4842 } else if (type != GROUPING) {
4843 ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
4844 bool is_positive = (type == POSITIVE_LOOKAHEAD);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004845 body = new(zone()) RegExpLookahead(body,
Steve Blocka7e24c12009-10-30 11:49:00 +00004846 is_positive,
4847 end_capture_index - capture_index,
4848 capture_index);
4849 }
4850 builder->AddAtom(body);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004851 // For compatability with JSC and ES3, we allow quantifiers after
4852 // lookaheads, and break in all cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00004853 break;
4854 }
4855 case '|': {
4856 Advance();
4857 builder->NewAlternative();
4858 continue;
4859 }
4860 case '*':
4861 case '+':
4862 case '?':
4863 return ReportError(CStrVector("Nothing to repeat"));
4864 case '^': {
4865 Advance();
4866 if (multiline_) {
4867 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004868 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE));
Steve Blocka7e24c12009-10-30 11:49:00 +00004869 } else {
4870 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004871 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT));
Steve Blocka7e24c12009-10-30 11:49:00 +00004872 set_contains_anchor();
4873 }
4874 continue;
4875 }
4876 case '$': {
4877 Advance();
4878 RegExpAssertion::Type type =
4879 multiline_ ? RegExpAssertion::END_OF_LINE :
4880 RegExpAssertion::END_OF_INPUT;
Ben Murdoch8b112d22011-06-08 16:22:53 +01004881 builder->AddAssertion(new(zone()) RegExpAssertion(type));
Steve Blocka7e24c12009-10-30 11:49:00 +00004882 continue;
4883 }
4884 case '.': {
4885 Advance();
4886 // everything except \x0a, \x0d, \u2028 and \u2029
Ben Murdoch257744e2011-11-30 15:57:28 +00004887 ZoneList<CharacterRange>* ranges =
4888 new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004889 CharacterRange::AddClassEscape('.', ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004890 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004891 builder->AddAtom(atom);
4892 break;
4893 }
4894 case '(': {
4895 SubexpressionType type = CAPTURE;
4896 Advance();
4897 if (current() == '?') {
4898 switch (Next()) {
4899 case ':':
4900 type = GROUPING;
4901 break;
4902 case '=':
4903 type = POSITIVE_LOOKAHEAD;
4904 break;
4905 case '!':
4906 type = NEGATIVE_LOOKAHEAD;
4907 break;
4908 default:
4909 ReportError(CStrVector("Invalid group") CHECK_FAILED);
4910 break;
4911 }
4912 Advance(2);
4913 } else {
4914 if (captures_ == NULL) {
Ben Murdoch257744e2011-11-30 15:57:28 +00004915 captures_ = new(zone()) ZoneList<RegExpCapture*>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004916 }
4917 if (captures_started() >= kMaxCaptures) {
4918 ReportError(CStrVector("Too many captures") CHECK_FAILED);
4919 }
4920 captures_->Add(NULL);
4921 }
4922 // Store current state and begin new disjunction parsing.
Ben Murdoch8b112d22011-06-08 16:22:53 +01004923 stored_state = new(zone()) RegExpParserState(stored_state,
Steve Blocka7e24c12009-10-30 11:49:00 +00004924 type,
4925 captures_started());
4926 builder = stored_state->builder();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004927 continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00004928 }
4929 case '[': {
4930 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
4931 builder->AddAtom(atom);
4932 break;
4933 }
4934 // Atom ::
4935 // \ AtomEscape
4936 case '\\':
4937 switch (Next()) {
4938 case kEndMarker:
4939 return ReportError(CStrVector("\\ at end of pattern"));
4940 case 'b':
4941 Advance(2);
4942 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004943 new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004944 continue;
4945 case 'B':
4946 Advance(2);
4947 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004948 new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004949 continue;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004950 // AtomEscape ::
4951 // CharacterClassEscape
4952 //
4953 // CharacterClassEscape :: one of
4954 // d D s S w W
Steve Blocka7e24c12009-10-30 11:49:00 +00004955 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
4956 uc32 c = Next();
4957 Advance(2);
Ben Murdoch257744e2011-11-30 15:57:28 +00004958 ZoneList<CharacterRange>* ranges =
4959 new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004960 CharacterRange::AddClassEscape(c, ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004961 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004962 builder->AddAtom(atom);
4963 break;
4964 }
4965 case '1': case '2': case '3': case '4': case '5': case '6':
4966 case '7': case '8': case '9': {
4967 int index = 0;
4968 if (ParseBackReferenceIndex(&index)) {
4969 RegExpCapture* capture = NULL;
4970 if (captures_ != NULL && index <= captures_->length()) {
4971 capture = captures_->at(index - 1);
4972 }
4973 if (capture == NULL) {
4974 builder->AddEmpty();
4975 break;
4976 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01004977 RegExpTree* atom = new(zone()) RegExpBackReference(capture);
Steve Blocka7e24c12009-10-30 11:49:00 +00004978 builder->AddAtom(atom);
4979 break;
4980 }
4981 uc32 first_digit = Next();
4982 if (first_digit == '8' || first_digit == '9') {
4983 // Treat as identity escape
4984 builder->AddCharacter(first_digit);
4985 Advance(2);
4986 break;
4987 }
4988 }
4989 // FALLTHROUGH
4990 case '0': {
4991 Advance();
4992 uc32 octal = ParseOctalLiteral();
4993 builder->AddCharacter(octal);
4994 break;
4995 }
4996 // ControlEscape :: one of
4997 // f n r t v
4998 case 'f':
4999 Advance(2);
5000 builder->AddCharacter('\f');
5001 break;
5002 case 'n':
5003 Advance(2);
5004 builder->AddCharacter('\n');
5005 break;
5006 case 'r':
5007 Advance(2);
5008 builder->AddCharacter('\r');
5009 break;
5010 case 't':
5011 Advance(2);
5012 builder->AddCharacter('\t');
5013 break;
5014 case 'v':
5015 Advance(2);
5016 builder->AddCharacter('\v');
5017 break;
5018 case 'c': {
Ben Murdoch086aeea2011-05-13 15:57:08 +01005019 Advance();
5020 uc32 controlLetter = Next();
5021 // Special case if it is an ASCII letter.
5022 // Convert lower case letters to uppercase.
5023 uc32 letter = controlLetter & ~('a' ^ 'A');
5024 if (letter < 'A' || 'Z' < letter) {
5025 // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
5026 // This is outside the specification. We match JSC in
5027 // reading the backslash as a literal character instead
5028 // of as starting an escape.
5029 builder->AddCharacter('\\');
5030 } else {
5031 Advance(2);
5032 builder->AddCharacter(controlLetter & 0x1f);
5033 }
Steve Blocka7e24c12009-10-30 11:49:00 +00005034 break;
5035 }
5036 case 'x': {
5037 Advance(2);
5038 uc32 value;
5039 if (ParseHexEscape(2, &value)) {
5040 builder->AddCharacter(value);
5041 } else {
5042 builder->AddCharacter('x');
5043 }
5044 break;
5045 }
5046 case 'u': {
5047 Advance(2);
5048 uc32 value;
5049 if (ParseHexEscape(4, &value)) {
5050 builder->AddCharacter(value);
5051 } else {
5052 builder->AddCharacter('u');
5053 }
5054 break;
5055 }
5056 default:
5057 // Identity escape.
5058 builder->AddCharacter(Next());
5059 Advance(2);
5060 break;
5061 }
5062 break;
5063 case '{': {
5064 int dummy;
5065 if (ParseIntervalQuantifier(&dummy, &dummy)) {
5066 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
5067 }
5068 // fallthrough
5069 }
5070 default:
5071 builder->AddCharacter(current());
5072 Advance();
5073 break;
5074 } // end switch(current())
5075
5076 int min;
5077 int max;
5078 switch (current()) {
5079 // QuantifierPrefix ::
5080 // *
5081 // +
5082 // ?
5083 // {
5084 case '*':
5085 min = 0;
5086 max = RegExpTree::kInfinity;
5087 Advance();
5088 break;
5089 case '+':
5090 min = 1;
5091 max = RegExpTree::kInfinity;
5092 Advance();
5093 break;
5094 case '?':
5095 min = 0;
5096 max = 1;
5097 Advance();
5098 break;
5099 case '{':
5100 if (ParseIntervalQuantifier(&min, &max)) {
5101 if (max < min) {
5102 ReportError(CStrVector("numbers out of order in {} quantifier.")
5103 CHECK_FAILED);
5104 }
5105 break;
5106 } else {
5107 continue;
5108 }
5109 default:
5110 continue;
5111 }
Leon Clarkee46be812010-01-19 14:06:41 +00005112 RegExpQuantifier::Type type = RegExpQuantifier::GREEDY;
Steve Blocka7e24c12009-10-30 11:49:00 +00005113 if (current() == '?') {
Leon Clarkee46be812010-01-19 14:06:41 +00005114 type = RegExpQuantifier::NON_GREEDY;
5115 Advance();
5116 } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
5117 // FLAG_regexp_possessive_quantifier is a debug-only flag.
5118 type = RegExpQuantifier::POSSESSIVE;
Steve Blocka7e24c12009-10-30 11:49:00 +00005119 Advance();
5120 }
Leon Clarkee46be812010-01-19 14:06:41 +00005121 builder->AddQuantifierToAtom(min, max, type);
Steve Blocka7e24c12009-10-30 11:49:00 +00005122 }
5123}
5124
Steve Blocka7e24c12009-10-30 11:49:00 +00005125
5126#ifdef DEBUG
5127// Currently only used in an ASSERT.
5128static bool IsSpecialClassEscape(uc32 c) {
5129 switch (c) {
5130 case 'd': case 'D':
5131 case 's': case 'S':
5132 case 'w': case 'W':
5133 return true;
5134 default:
5135 return false;
5136 }
5137}
5138#endif
5139
5140
5141// In order to know whether an escape is a backreference or not we have to scan
5142// the entire regexp and find the number of capturing parentheses. However we
5143// don't want to scan the regexp twice unless it is necessary. This mini-parser
5144// is called when needed. It can see the difference between capturing and
5145// noncapturing parentheses and can skip character classes and backslash-escaped
5146// characters.
5147void RegExpParser::ScanForCaptures() {
5148 // Start with captures started previous to current position
5149 int capture_count = captures_started();
5150 // Add count of captures after this position.
5151 int n;
5152 while ((n = current()) != kEndMarker) {
5153 Advance();
5154 switch (n) {
5155 case '\\':
5156 Advance();
5157 break;
5158 case '[': {
5159 int c;
5160 while ((c = current()) != kEndMarker) {
5161 Advance();
5162 if (c == '\\') {
5163 Advance();
5164 } else {
5165 if (c == ']') break;
5166 }
5167 }
5168 break;
5169 }
5170 case '(':
5171 if (current() != '?') capture_count++;
5172 break;
5173 }
5174 }
5175 capture_count_ = capture_count;
5176 is_scanned_for_captures_ = true;
5177}
5178
5179
5180bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
5181 ASSERT_EQ('\\', current());
5182 ASSERT('1' <= Next() && Next() <= '9');
5183 // Try to parse a decimal literal that is no greater than the total number
5184 // of left capturing parentheses in the input.
5185 int start = position();
5186 int value = Next() - '0';
5187 Advance(2);
5188 while (true) {
5189 uc32 c = current();
5190 if (IsDecimalDigit(c)) {
5191 value = 10 * value + (c - '0');
5192 if (value > kMaxCaptures) {
5193 Reset(start);
5194 return false;
5195 }
5196 Advance();
5197 } else {
5198 break;
5199 }
5200 }
5201 if (value > captures_started()) {
5202 if (!is_scanned_for_captures_) {
5203 int saved_position = position();
5204 ScanForCaptures();
5205 Reset(saved_position);
5206 }
5207 if (value > capture_count_) {
5208 Reset(start);
5209 return false;
5210 }
5211 }
5212 *index_out = value;
5213 return true;
5214}
5215
5216
5217// QuantifierPrefix ::
5218// { DecimalDigits }
5219// { DecimalDigits , }
5220// { DecimalDigits , DecimalDigits }
5221//
5222// Returns true if parsing succeeds, and set the min_out and max_out
5223// values. Values are truncated to RegExpTree::kInfinity if they overflow.
5224bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
5225 ASSERT_EQ(current(), '{');
5226 int start = position();
5227 Advance();
5228 int min = 0;
5229 if (!IsDecimalDigit(current())) {
5230 Reset(start);
5231 return false;
5232 }
5233 while (IsDecimalDigit(current())) {
5234 int next = current() - '0';
5235 if (min > (RegExpTree::kInfinity - next) / 10) {
5236 // Overflow. Skip past remaining decimal digits and return -1.
5237 do {
5238 Advance();
5239 } while (IsDecimalDigit(current()));
5240 min = RegExpTree::kInfinity;
5241 break;
5242 }
5243 min = 10 * min + next;
5244 Advance();
5245 }
5246 int max = 0;
5247 if (current() == '}') {
5248 max = min;
5249 Advance();
5250 } else if (current() == ',') {
5251 Advance();
5252 if (current() == '}') {
5253 max = RegExpTree::kInfinity;
5254 Advance();
5255 } else {
5256 while (IsDecimalDigit(current())) {
5257 int next = current() - '0';
5258 if (max > (RegExpTree::kInfinity - next) / 10) {
5259 do {
5260 Advance();
5261 } while (IsDecimalDigit(current()));
5262 max = RegExpTree::kInfinity;
5263 break;
5264 }
5265 max = 10 * max + next;
5266 Advance();
5267 }
5268 if (current() != '}') {
5269 Reset(start);
5270 return false;
5271 }
5272 Advance();
5273 }
5274 } else {
5275 Reset(start);
5276 return false;
5277 }
5278 *min_out = min;
5279 *max_out = max;
5280 return true;
5281}
5282
5283
Steve Blocka7e24c12009-10-30 11:49:00 +00005284uc32 RegExpParser::ParseOctalLiteral() {
5285 ASSERT('0' <= current() && current() <= '7');
5286 // For compatibility with some other browsers (not all), we parse
5287 // up to three octal digits with a value below 256.
5288 uc32 value = current() - '0';
5289 Advance();
5290 if ('0' <= current() && current() <= '7') {
5291 value = value * 8 + current() - '0';
5292 Advance();
5293 if (value < 32 && '0' <= current() && current() <= '7') {
5294 value = value * 8 + current() - '0';
5295 Advance();
5296 }
5297 }
5298 return value;
5299}
5300
5301
5302bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
5303 int start = position();
5304 uc32 val = 0;
5305 bool done = false;
5306 for (int i = 0; !done; i++) {
5307 uc32 c = current();
5308 int d = HexValue(c);
5309 if (d < 0) {
5310 Reset(start);
5311 return false;
5312 }
5313 val = val * 16 + d;
5314 Advance();
5315 if (i == length - 1) {
5316 done = true;
5317 }
5318 }
5319 *value = val;
5320 return true;
5321}
5322
5323
5324uc32 RegExpParser::ParseClassCharacterEscape() {
5325 ASSERT(current() == '\\');
5326 ASSERT(has_next() && !IsSpecialClassEscape(Next()));
5327 Advance();
5328 switch (current()) {
5329 case 'b':
5330 Advance();
5331 return '\b';
5332 // ControlEscape :: one of
5333 // f n r t v
5334 case 'f':
5335 Advance();
5336 return '\f';
5337 case 'n':
5338 Advance();
5339 return '\n';
5340 case 'r':
5341 Advance();
5342 return '\r';
5343 case 't':
5344 Advance();
5345 return '\t';
5346 case 'v':
5347 Advance();
5348 return '\v';
Ben Murdoch086aeea2011-05-13 15:57:08 +01005349 case 'c': {
5350 uc32 controlLetter = Next();
5351 uc32 letter = controlLetter & ~('A' ^ 'a');
5352 // For compatibility with JSC, inside a character class
5353 // we also accept digits and underscore as control characters.
5354 if ((controlLetter >= '0' && controlLetter <= '9') ||
5355 controlLetter == '_' ||
5356 (letter >= 'A' && letter <= 'Z')) {
5357 Advance(2);
5358 // Control letters mapped to ASCII control characters in the range
5359 // 0x00-0x1f.
5360 return controlLetter & 0x1f;
5361 }
5362 // We match JSC in reading the backslash as a literal
5363 // character instead of as starting an escape.
5364 return '\\';
5365 }
Steve Blocka7e24c12009-10-30 11:49:00 +00005366 case '0': case '1': case '2': case '3': case '4': case '5':
5367 case '6': case '7':
5368 // For compatibility, we interpret a decimal escape that isn't
5369 // a back reference (and therefore either \0 or not valid according
5370 // to the specification) as a 1..3 digit octal character code.
5371 return ParseOctalLiteral();
5372 case 'x': {
5373 Advance();
5374 uc32 value;
5375 if (ParseHexEscape(2, &value)) {
5376 return value;
5377 }
5378 // If \x is not followed by a two-digit hexadecimal, treat it
5379 // as an identity escape.
5380 return 'x';
5381 }
5382 case 'u': {
5383 Advance();
5384 uc32 value;
5385 if (ParseHexEscape(4, &value)) {
5386 return value;
5387 }
5388 // If \u is not followed by a four-digit hexadecimal, treat it
5389 // as an identity escape.
5390 return 'u';
5391 }
5392 default: {
5393 // Extended identity escape. We accept any character that hasn't
5394 // been matched by a more specific case, not just the subset required
5395 // by the ECMAScript specification.
5396 uc32 result = current();
5397 Advance();
5398 return result;
5399 }
5400 }
5401 return 0;
5402}
5403
5404
5405CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
5406 ASSERT_EQ(0, *char_class);
5407 uc32 first = current();
5408 if (first == '\\') {
5409 switch (Next()) {
5410 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
5411 *char_class = Next();
5412 Advance(2);
5413 return CharacterRange::Singleton(0); // Return dummy value.
5414 }
5415 case kEndMarker:
5416 return ReportError(CStrVector("\\ at end of pattern"));
5417 default:
5418 uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
5419 return CharacterRange::Singleton(c);
5420 }
5421 } else {
5422 Advance();
5423 return CharacterRange::Singleton(first);
5424 }
5425}
5426
5427
Ben Murdochb0fe1622011-05-05 13:52:32 +01005428static const uc16 kNoCharClass = 0;
5429
5430// Adds range or pre-defined character class to character ranges.
5431// If char_class is not kInvalidClass, it's interpreted as a class
5432// escape (i.e., 's' means whitespace, from '\s').
5433static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
5434 uc16 char_class,
5435 CharacterRange range) {
5436 if (char_class != kNoCharClass) {
5437 CharacterRange::AddClassEscape(char_class, ranges);
5438 } else {
5439 ranges->Add(range);
5440 }
5441}
5442
5443
Steve Blocka7e24c12009-10-30 11:49:00 +00005444RegExpTree* RegExpParser::ParseCharacterClass() {
5445 static const char* kUnterminated = "Unterminated character class";
5446 static const char* kRangeOutOfOrder = "Range out of order in character class";
5447
5448 ASSERT_EQ(current(), '[');
5449 Advance();
5450 bool is_negated = false;
5451 if (current() == '^') {
5452 is_negated = true;
5453 Advance();
5454 }
Ben Murdoch257744e2011-11-30 15:57:28 +00005455 ZoneList<CharacterRange>* ranges = new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00005456 while (has_more() && current() != ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01005457 uc16 char_class = kNoCharClass;
Steve Blocka7e24c12009-10-30 11:49:00 +00005458 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00005459 if (current() == '-') {
5460 Advance();
5461 if (current() == kEndMarker) {
5462 // If we reach the end we break out of the loop and let the
5463 // following code report an error.
5464 break;
5465 } else if (current() == ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01005466 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00005467 ranges->Add(CharacterRange::Singleton('-'));
5468 break;
5469 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01005470 uc16 char_class_2 = kNoCharClass;
5471 CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
5472 if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
5473 // Either end is an escaped character class. Treat the '-' verbatim.
5474 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00005475 ranges->Add(CharacterRange::Singleton('-'));
Ben Murdochb0fe1622011-05-05 13:52:32 +01005476 AddRangeOrEscape(ranges, char_class_2, next);
Steve Blocka7e24c12009-10-30 11:49:00 +00005477 continue;
5478 }
5479 if (first.from() > next.to()) {
5480 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
5481 }
5482 ranges->Add(CharacterRange::Range(first.from(), next.to()));
5483 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01005484 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00005485 }
5486 }
5487 if (!has_more()) {
5488 return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
5489 }
5490 Advance();
5491 if (ranges->length() == 0) {
5492 ranges->Add(CharacterRange::Everything());
5493 is_negated = !is_negated;
5494 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01005495 return new(zone()) RegExpCharacterClass(ranges, is_negated);
Steve Blocka7e24c12009-10-30 11:49:00 +00005496}
5497
5498
5499// ----------------------------------------------------------------------------
5500// The Parser interface.
5501
Steve Blocka7e24c12009-10-30 11:49:00 +00005502ParserMessage::~ParserMessage() {
5503 for (int i = 0; i < args().length(); i++)
5504 DeleteArray(args()[i]);
5505 DeleteArray(args().start());
5506}
5507
5508
5509ScriptDataImpl::~ScriptDataImpl() {
Iain Merrick9ac36c92010-09-13 15:29:50 +01005510 if (owns_store_) store_.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00005511}
5512
5513
5514int ScriptDataImpl::Length() {
Leon Clarkef7060e22010-06-03 12:02:55 +01005515 return store_.length() * sizeof(unsigned);
Steve Blocka7e24c12009-10-30 11:49:00 +00005516}
5517
5518
Leon Clarkef7060e22010-06-03 12:02:55 +01005519const char* ScriptDataImpl::Data() {
5520 return reinterpret_cast<const char*>(store_.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00005521}
5522
5523
Leon Clarkee46be812010-01-19 14:06:41 +00005524bool ScriptDataImpl::HasError() {
5525 return has_error();
5526}
5527
5528
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005529void ScriptDataImpl::Initialize() {
5530 // Prepares state for use.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005531 if (store_.length() >= PreparseDataConstants::kHeaderSize) {
5532 function_index_ = PreparseDataConstants::kHeaderSize;
5533 int symbol_data_offset = PreparseDataConstants::kHeaderSize
5534 + store_[PreparseDataConstants::kFunctionsSizeOffset];
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005535 if (store_.length() > symbol_data_offset) {
5536 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
5537 } else {
5538 // Partial preparse causes no symbol information.
5539 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5540 }
5541 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5542 }
5543}
5544
5545
5546int ScriptDataImpl::ReadNumber(byte** source) {
5547 // Reads a number from symbol_data_ in base 128. The most significant
5548 // bit marks that there are more digits.
5549 // If the first byte is 0x80 (kNumberTerminator), it would normally
5550 // represent a leading zero. Since that is useless, and therefore won't
5551 // appear as the first digit of any actual value, it is used to
5552 // mark the end of the input stream.
5553 byte* data = *source;
5554 if (data >= symbol_data_end_) return -1;
5555 byte input = *data;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005556 if (input == PreparseDataConstants::kNumberTerminator) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005557 // End of stream marker.
5558 return -1;
5559 }
5560 int result = input & 0x7f;
5561 data++;
5562 while ((input & 0x80u) != 0) {
5563 if (data >= symbol_data_end_) return -1;
5564 input = *data;
5565 result = (result << 7) | (input & 0x7f);
5566 data++;
5567 }
5568 *source = data;
5569 return result;
5570}
5571
5572
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005573// Create a Scanner for the preparser to use as input, and preparse the source.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005574static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005575 int flags,
5576 ParserRecorder* recorder) {
Steve Block44f0eee2011-05-26 01:26:41 +01005577 Isolate* isolate = Isolate::Current();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005578 HistogramTimerScope timer(isolate->counters()->pre_parse());
5579 Scanner scanner(isolate->unicode_cache());
5580 scanner.SetHarmonyScoping(FLAG_harmony_scoping);
Steve Block9fac8402011-05-12 15:51:54 +01005581 scanner.Initialize(source);
Steve Block44f0eee2011-05-26 01:26:41 +01005582 intptr_t stack_limit = isolate->stack_guard()->real_climit();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005583 preparser::PreParser::PreParseResult result =
5584 preparser::PreParser::PreParseProgram(&scanner,
5585 recorder,
5586 flags,
5587 stack_limit);
5588 if (result == preparser::PreParser::kPreParseStackOverflow) {
Steve Block44f0eee2011-05-26 01:26:41 +01005589 isolate->StackOverflow();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005590 return NULL;
5591 }
5592
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005593 // Extract the accumulated data from the recorder as a single
5594 // contiguous vector that we are responsible for disposing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005595 Vector<unsigned> store = recorder->ExtractData();
Steve Blocka7e24c12009-10-30 11:49:00 +00005596 return new ScriptDataImpl(store);
5597}
5598
5599
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005600// Preparse, but only collect data that is immediately useful,
5601// even if the preparser data is only used once.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005602ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005603 v8::Extension* extension,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005604 int flags) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005605 bool allow_lazy = FLAG_lazy && (extension == NULL);
5606 if (!allow_lazy) {
5607 // Partial preparsing is only about lazily compiled functions.
5608 // If we don't allow lazy compilation, the log data will be empty.
5609 return NULL;
5610 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005611 flags |= kAllowLazy;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005612 PartialParserRecorder recorder;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005613 int source_length = source->length();
5614 if (source->IsExternalTwoByteString()) {
5615 ExternalTwoByteStringUC16CharacterStream stream(
5616 Handle<ExternalTwoByteString>::cast(source), 0, source_length);
5617 return DoPreParse(&stream, flags, &recorder);
5618 } else {
5619 GenericStringUC16CharacterStream stream(source, 0, source_length);
5620 return DoPreParse(&stream, flags, &recorder);
5621 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005622}
5623
5624
Ben Murdochb0fe1622011-05-05 13:52:32 +01005625ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005626 v8::Extension* extension,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005627 int flags) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005628 Handle<Script> no_script;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005629 if (FLAG_lazy && (extension == NULL)) {
5630 flags |= kAllowLazy;
5631 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005632 CompleteParserRecorder recorder;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005633 return DoPreParse(source, flags, &recorder);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005634}
5635
5636
5637bool RegExpParser::ParseRegExp(FlatStringReader* input,
5638 bool multiline,
5639 RegExpCompileData* result) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005640 ASSERT(result != NULL);
5641 RegExpParser parser(input, &result->error, multiline);
5642 RegExpTree* tree = parser.ParsePattern();
5643 if (parser.failed()) {
5644 ASSERT(tree == NULL);
5645 ASSERT(!result->error.is_null());
5646 } else {
5647 ASSERT(tree != NULL);
5648 ASSERT(result->error.is_null());
5649 result->tree = tree;
5650 int capture_count = parser.captures_started();
5651 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
5652 result->contains_anchor = parser.contains_anchor();
5653 result->capture_count = capture_count;
5654 }
5655 return !parser.failed();
5656}
5657
5658
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005659bool ParserApi::Parse(CompilationInfo* info, int parsing_flags) {
Ben Murdochf87a2032010-10-22 12:50:53 +01005660 ASSERT(info->function() == NULL);
5661 FunctionLiteral* result = NULL;
5662 Handle<Script> script = info->script();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005663 ASSERT((parsing_flags & kLanguageModeMask) == CLASSIC_MODE);
5664 if (!info->is_native() && FLAG_harmony_scoping) {
5665 // Harmony scoping is requested.
5666 parsing_flags |= EXTENDED_MODE;
5667 }
5668 if (FLAG_allow_natives_syntax || info->is_native()) {
5669 // We requre %identifier(..) syntax.
5670 parsing_flags |= kAllowNativesSyntax;
5671 }
Ben Murdochf87a2032010-10-22 12:50:53 +01005672 if (info->is_lazy()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005673 ASSERT(!info->is_eval());
5674 Parser parser(script, parsing_flags, NULL, NULL);
Steve Block44f0eee2011-05-26 01:26:41 +01005675 result = parser.ParseLazy(info);
Leon Clarke4515c472010-02-03 11:58:03 +00005676 } else {
Ben Murdochf87a2032010-10-22 12:50:53 +01005677 ScriptDataImpl* pre_data = info->pre_parse_data();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005678 Parser parser(script, parsing_flags, info->extension(), pre_data);
Ben Murdochf87a2032010-10-22 12:50:53 +01005679 if (pre_data != NULL && pre_data->has_error()) {
5680 Scanner::Location loc = pre_data->MessageLocation();
5681 const char* message = pre_data->BuildMessage();
5682 Vector<const char*> args = pre_data->BuildArgs();
5683 parser.ReportMessageAt(loc, message, args);
5684 DeleteArray(message);
5685 for (int i = 0; i < args.length(); i++) {
5686 DeleteArray(args[i]);
5687 }
5688 DeleteArray(args.start());
Steve Block44f0eee2011-05-26 01:26:41 +01005689 ASSERT(info->isolate()->has_pending_exception());
Ben Murdochf87a2032010-10-22 12:50:53 +01005690 } else {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00005691 result = parser.ParseProgram(info);
Ben Murdochf87a2032010-10-22 12:50:53 +01005692 }
Leon Clarke4515c472010-02-03 11:58:03 +00005693 }
Ben Murdochf87a2032010-10-22 12:50:53 +01005694 info->SetFunction(result);
5695 return (result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00005696}
5697
Steve Blocka7e24c12009-10-30 11:49:00 +00005698} } // namespace v8::internal