blob: f8c7c416f3449e8af6fdcdda53be770a1abe2b72 [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 Murdoch257744e2011-11-30 15:57:28 +000031#include "ast-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000032#include "bootstrapper.h"
Steve Block6ded16b2010-05-10 14:33:55 +010033#include "codegen.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034#include "compiler.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +010035#include "func-name-inferrer.h"
Steve Block6ded16b2010-05-10 14:33:55 +010036#include "messages.h"
Kristian Monsen25f61362010-05-21 11:50:48 +010037#include "parser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038#include "platform.h"
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080039#include "preparser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000040#include "runtime.h"
Ben Murdoch3bec4d22010-07-22 14:51:16 +010041#include "scopeinfo.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000042#include "string-stream.h"
43
44namespace v8 {
45namespace internal {
46
Steve Blocka7e24c12009-10-30 11:49:00 +000047// PositionStack is used for on-stack allocation of token positions for
48// new expressions. Please look at ParseNewExpression.
49
50class PositionStack {
51 public:
52 explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
53 ~PositionStack() { ASSERT(!*ok_ || is_empty()); }
54
55 class Element {
56 public:
57 Element(PositionStack* stack, int value) {
58 previous_ = stack->top();
59 value_ = value;
60 stack->set_top(this);
61 }
62
63 private:
64 Element* previous() { return previous_; }
65 int value() { return value_; }
66 friend class PositionStack;
67 Element* previous_;
68 int value_;
69 };
70
71 bool is_empty() { return top_ == NULL; }
72 int pop() {
73 ASSERT(!is_empty());
74 int result = top_->value();
75 top_ = top_->previous();
76 return result;
77 }
78
79 private:
80 Element* top() { return top_; }
81 void set_top(Element* value) { top_ = value; }
82 Element* top_;
83 bool* ok_;
84};
85
86
Steve Blocka7e24c12009-10-30 11:49:00 +000087RegExpBuilder::RegExpBuilder()
Ben Murdoch8b112d22011-06-08 16:22:53 +010088 : zone_(Isolate::Current()->zone()),
89 pending_empty_(false),
90 characters_(NULL),
91 terms_(),
92 alternatives_()
Steve Blocka7e24c12009-10-30 11:49:00 +000093#ifdef DEBUG
Ben Murdoch8b112d22011-06-08 16:22:53 +010094 , last_added_(ADD_NONE)
Steve Blocka7e24c12009-10-30 11:49:00 +000095#endif
96 {}
97
98
99void RegExpBuilder::FlushCharacters() {
100 pending_empty_ = false;
101 if (characters_ != NULL) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100102 RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector());
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 characters_ = NULL;
104 text_.Add(atom);
105 LAST(ADD_ATOM);
106 }
107}
108
109
110void RegExpBuilder::FlushText() {
111 FlushCharacters();
112 int num_text = text_.length();
113 if (num_text == 0) {
114 return;
115 } else if (num_text == 1) {
116 terms_.Add(text_.last());
117 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100118 RegExpText* text = new(zone()) RegExpText();
Steve Blocka7e24c12009-10-30 11:49:00 +0000119 for (int i = 0; i < num_text; i++)
120 text_.Get(i)->AppendToText(text);
121 terms_.Add(text);
122 }
123 text_.Clear();
124}
125
126
127void RegExpBuilder::AddCharacter(uc16 c) {
128 pending_empty_ = false;
129 if (characters_ == NULL) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000130 characters_ = new(zone()) ZoneList<uc16>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000131 }
132 characters_->Add(c);
133 LAST(ADD_CHAR);
134}
135
136
137void RegExpBuilder::AddEmpty() {
138 pending_empty_ = true;
139}
140
141
142void RegExpBuilder::AddAtom(RegExpTree* term) {
143 if (term->IsEmpty()) {
144 AddEmpty();
145 return;
146 }
147 if (term->IsTextElement()) {
148 FlushCharacters();
149 text_.Add(term);
150 } else {
151 FlushText();
152 terms_.Add(term);
153 }
154 LAST(ADD_ATOM);
155}
156
157
158void RegExpBuilder::AddAssertion(RegExpTree* assert) {
159 FlushText();
160 terms_.Add(assert);
161 LAST(ADD_ASSERT);
162}
163
164
165void RegExpBuilder::NewAlternative() {
166 FlushTerms();
167}
168
169
170void RegExpBuilder::FlushTerms() {
171 FlushText();
172 int num_terms = terms_.length();
173 RegExpTree* alternative;
174 if (num_terms == 0) {
175 alternative = RegExpEmpty::GetInstance();
176 } else if (num_terms == 1) {
177 alternative = terms_.last();
178 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100179 alternative = new(zone()) RegExpAlternative(terms_.GetList());
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 }
181 alternatives_.Add(alternative);
182 terms_.Clear();
183 LAST(ADD_NONE);
184}
185
186
187RegExpTree* RegExpBuilder::ToRegExp() {
188 FlushTerms();
189 int num_alternatives = alternatives_.length();
190 if (num_alternatives == 0) {
191 return RegExpEmpty::GetInstance();
192 }
193 if (num_alternatives == 1) {
194 return alternatives_.last();
195 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100196 return new(zone()) RegExpDisjunction(alternatives_.GetList());
Steve Blocka7e24c12009-10-30 11:49:00 +0000197}
198
199
Leon Clarkee46be812010-01-19 14:06:41 +0000200void RegExpBuilder::AddQuantifierToAtom(int min,
201 int max,
202 RegExpQuantifier::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000203 if (pending_empty_) {
204 pending_empty_ = false;
205 return;
206 }
207 RegExpTree* atom;
208 if (characters_ != NULL) {
209 ASSERT(last_added_ == ADD_CHAR);
210 // Last atom was character.
211 Vector<const uc16> char_vector = characters_->ToConstVector();
212 int num_chars = char_vector.length();
213 if (num_chars > 1) {
214 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100215 text_.Add(new(zone()) RegExpAtom(prefix));
Steve Blocka7e24c12009-10-30 11:49:00 +0000216 char_vector = char_vector.SubVector(num_chars - 1, num_chars);
217 }
218 characters_ = NULL;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100219 atom = new(zone()) RegExpAtom(char_vector);
Steve Blocka7e24c12009-10-30 11:49:00 +0000220 FlushText();
221 } else if (text_.length() > 0) {
222 ASSERT(last_added_ == ADD_ATOM);
223 atom = text_.RemoveLast();
224 FlushText();
225 } else if (terms_.length() > 0) {
226 ASSERT(last_added_ == ADD_ATOM);
227 atom = terms_.RemoveLast();
228 if (atom->max_match() == 0) {
229 // Guaranteed to only match an empty string.
230 LAST(ADD_TERM);
231 if (min == 0) {
232 return;
233 }
234 terms_.Add(atom);
235 return;
236 }
237 } else {
238 // Only call immediately after adding an atom or character!
239 UNREACHABLE();
240 return;
241 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100242 terms_.Add(new(zone()) RegExpQuantifier(min, max, type, atom));
Steve Blocka7e24c12009-10-30 11:49:00 +0000243 LAST(ADD_TERM);
244}
245
246
Steve Block9fac8402011-05-12 15:51:54 +0100247Handle<String> Parser::LookupSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800248 // Length of symbol cache is the number of identified symbols.
249 // If we are larger than that, or negative, it's not a cached symbol.
250 // This might also happen if there is no preparser symbol data, even
251 // if there is some preparser data.
252 if (static_cast<unsigned>(symbol_id)
253 >= static_cast<unsigned>(symbol_cache_.length())) {
Steve Block9fac8402011-05-12 15:51:54 +0100254 if (scanner().is_literal_ascii()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100255 return isolate()->factory()->LookupAsciiSymbol(
256 scanner().literal_ascii_string());
Steve Block9fac8402011-05-12 15:51:54 +0100257 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100258 return isolate()->factory()->LookupTwoByteSymbol(
259 scanner().literal_uc16_string());
Steve Block9fac8402011-05-12 15:51:54 +0100260 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800261 }
Steve Block9fac8402011-05-12 15:51:54 +0100262 return LookupCachedSymbol(symbol_id);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800263}
264
265
Steve Block9fac8402011-05-12 15:51:54 +0100266Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800267 // Make sure the cache is large enough to hold the symbol identifier.
268 if (symbol_cache_.length() <= symbol_id) {
269 // Increase length to index + 1.
270 symbol_cache_.AddBlock(Handle<String>::null(),
271 symbol_id + 1 - symbol_cache_.length());
272 }
273 Handle<String> result = symbol_cache_.at(symbol_id);
274 if (result.is_null()) {
Steve Block9fac8402011-05-12 15:51:54 +0100275 if (scanner().is_literal_ascii()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100276 result = isolate()->factory()->LookupAsciiSymbol(
277 scanner().literal_ascii_string());
Steve Block9fac8402011-05-12 15:51:54 +0100278 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100279 result = isolate()->factory()->LookupTwoByteSymbol(
280 scanner().literal_uc16_string());
Steve Block9fac8402011-05-12 15:51:54 +0100281 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800282 symbol_cache_.at(symbol_id) = result;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100283 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000284 }
Steve Block44f0eee2011-05-26 01:26:41 +0100285 isolate()->counters()->total_preparse_symbols_skipped()->Increment();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800286 return result;
287}
Steve Blocka7e24c12009-10-30 11:49:00 +0000288
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800289
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100290FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
291 // The current pre-data entry must be a FunctionEntry with the given
292 // start position.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100293 if ((function_index_ + FunctionEntry::kSize <= store_.length())
294 && (static_cast<int>(store_[function_index_]) == start)) {
295 int index = function_index_;
296 function_index_ += FunctionEntry::kSize;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100297 return FunctionEntry(store_.SubVector(index,
298 index + FunctionEntry::kSize));
Steve Blocka7e24c12009-10-30 11:49:00 +0000299 }
300 return FunctionEntry();
301}
302
303
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100304int ScriptDataImpl::GetSymbolIdentifier() {
305 return ReadNumber(&symbol_data_);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100306}
307
308
Iain Merrick9ac36c92010-09-13 15:29:50 +0100309bool ScriptDataImpl::SanityCheck() {
310 // Check that the header data is valid and doesn't specify
311 // point to positions outside the store.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800312 if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
313 if (magic() != PreparseDataConstants::kMagicNumber) return false;
314 if (version() != PreparseDataConstants::kCurrentVersion) return false;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100315 if (has_error()) {
316 // Extra sane sanity check for error message encoding.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800317 if (store_.length() <= PreparseDataConstants::kHeaderSize
318 + PreparseDataConstants::kMessageTextPos) {
319 return false;
320 }
321 if (Read(PreparseDataConstants::kMessageStartPos) >
322 Read(PreparseDataConstants::kMessageEndPos)) {
323 return false;
324 }
325 unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
326 int pos = PreparseDataConstants::kMessageTextPos;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100327 for (unsigned int i = 0; i <= arg_count; i++) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800328 if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
329 return false;
330 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100331 int length = static_cast<int>(Read(pos));
332 if (length < 0) return false;
333 pos += 1 + length;
334 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800335 if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
336 return false;
337 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100338 return true;
339 }
340 // Check that the space allocated for function entries is sane.
341 int functions_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800342 static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100343 if (functions_size < 0) return false;
344 if (functions_size % FunctionEntry::kSize != 0) return false;
345 // Check that the count of symbols is non-negative.
346 int symbol_count =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800347 static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100348 if (symbol_count < 0) return false;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100349 // Check that the total size has room for header and function entries.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100350 int minimum_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800351 PreparseDataConstants::kHeaderSize + functions_size;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100352 if (store_.length() < minimum_size) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000353 return true;
354}
355
356
Steve Block59151502010-09-22 15:07:15 +0100357
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100358const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000359 int length = start[0];
360 char* result = NewArray<char>(length + 1);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100361 for (int i = 0; i < length; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000362 result[i] = start[i + 1];
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100363 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000364 result[length] = '\0';
365 if (chars != NULL) *chars = length;
366 return result;
367}
368
Steve Blocka7e24c12009-10-30 11:49:00 +0000369Scanner::Location ScriptDataImpl::MessageLocation() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800370 int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
371 int end_pos = Read(PreparseDataConstants::kMessageEndPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000372 return Scanner::Location(beg_pos, end_pos);
373}
374
375
376const char* ScriptDataImpl::BuildMessage() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800377 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100378 return ReadString(start, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000379}
380
381
382Vector<const char*> ScriptDataImpl::BuildArgs() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800383 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000384 const char** array = NewArray<const char*>(arg_count);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100385 // Position after text found by skipping past length field and
386 // length field content words.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800387 int pos = PreparseDataConstants::kMessageTextPos + 1
388 + Read(PreparseDataConstants::kMessageTextPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000389 for (int i = 0; i < arg_count; i++) {
390 int count = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100391 array[i] = ReadString(ReadAddress(pos), &count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000392 pos += count + 1;
393 }
394 return Vector<const char*>(array, arg_count);
395}
396
397
398unsigned ScriptDataImpl::Read(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800399 return store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000400}
401
402
403unsigned* ScriptDataImpl::ReadAddress(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800404 return &store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000405}
406
407
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800408Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100409 Scope* result = new(zone()) Scope(parent, type);
Steve Blocka7e24c12009-10-30 11:49:00 +0000410 result->Initialize(inside_with);
411 return result;
412}
413
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000414
Steve Blocka7e24c12009-10-30 11:49:00 +0000415// ----------------------------------------------------------------------------
416// Target is a support class to facilitate manipulation of the
417// Parser's target_stack_ (the stack of potential 'break' and
418// 'continue' statement targets). Upon construction, a new target is
419// added; it is removed upon destruction.
420
421class Target BASE_EMBEDDED {
422 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800423 Target(Target** variable, AstNode* node)
424 : variable_(variable), node_(node), previous_(*variable) {
425 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000426 }
427
428 ~Target() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800429 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000430 }
431
432 Target* previous() { return previous_; }
433 AstNode* node() { return node_; }
434
435 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800436 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000437 AstNode* node_;
438 Target* previous_;
439};
440
441
442class TargetScope BASE_EMBEDDED {
443 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800444 explicit TargetScope(Target** variable)
445 : variable_(variable), previous_(*variable) {
446 *variable = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000447 }
448
449 ~TargetScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800450 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000451 }
452
453 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800454 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000455 Target* previous_;
456};
457
458
459// ----------------------------------------------------------------------------
460// LexicalScope is a support class to facilitate manipulation of the
461// Parser's scope stack. The constructor sets the parser's top scope
462// to the incoming scope, and the destructor resets it.
Steve Block44f0eee2011-05-26 01:26:41 +0100463//
Ben Murdoch8b112d22011-06-08 16:22:53 +0100464// Additionally, it stores transient information used during parsing.
Steve Block44f0eee2011-05-26 01:26:41 +0100465// These scopes are not kept around after parsing or referenced by syntax
466// trees so they can be stack-allocated and hence used by the pre-parser.
Steve Blocka7e24c12009-10-30 11:49:00 +0000467
468class LexicalScope BASE_EMBEDDED {
469 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100470 LexicalScope(Parser* parser, Scope* scope, Isolate* isolate);
471 ~LexicalScope();
472
473 int NextMaterializedLiteralIndex() {
474 int next_index =
475 materialized_literal_count_ + JSFunction::kLiteralsPrefixSize;
476 materialized_literal_count_++;
477 return next_index;
478 }
479 int materialized_literal_count() { return materialized_literal_count_; }
480
481 void SetThisPropertyAssignmentInfo(
482 bool only_simple_this_property_assignments,
483 Handle<FixedArray> this_property_assignments) {
484 only_simple_this_property_assignments_ =
485 only_simple_this_property_assignments;
486 this_property_assignments_ = this_property_assignments;
487 }
488 bool only_simple_this_property_assignments() {
489 return only_simple_this_property_assignments_;
490 }
491 Handle<FixedArray> this_property_assignments() {
492 return this_property_assignments_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000493 }
494
Steve Block44f0eee2011-05-26 01:26:41 +0100495 void AddProperty() { expected_property_count_++; }
496 int expected_property_count() { return expected_property_count_; }
497
Steve Blocka7e24c12009-10-30 11:49:00 +0000498 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100499 // Captures the number of literals that need materialization in the
500 // function. Includes regexp literals, and boilerplate for object
501 // and array literals.
502 int materialized_literal_count_;
503
504 // Properties count estimation.
505 int expected_property_count_;
506
507 // Keeps track of assignments to properties of this. Used for
508 // optimizing constructors.
509 bool only_simple_this_property_assignments_;
510 Handle<FixedArray> this_property_assignments_;
511
Steve Block44f0eee2011-05-26 01:26:41 +0100512 // Bookkeeping
513 Parser* parser_;
514 // Previous values
515 LexicalScope* lexical_scope_parent_;
516 Scope* previous_scope_;
517 int previous_with_nesting_level_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100518 unsigned previous_ast_node_id_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000519};
520
Steve Block44f0eee2011-05-26 01:26:41 +0100521
522LexicalScope::LexicalScope(Parser* parser, Scope* scope, Isolate* isolate)
523 : materialized_literal_count_(0),
524 expected_property_count_(0),
525 only_simple_this_property_assignments_(false),
526 this_property_assignments_(isolate->factory()->empty_fixed_array()),
Steve Block44f0eee2011-05-26 01:26:41 +0100527 parser_(parser),
528 lexical_scope_parent_(parser->lexical_scope_),
529 previous_scope_(parser->top_scope_),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100530 previous_with_nesting_level_(parser->with_nesting_level_),
531 previous_ast_node_id_(isolate->ast_node_id()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100532 parser->top_scope_ = scope;
533 parser->lexical_scope_ = this;
534 parser->with_nesting_level_ = 0;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100535 isolate->set_ast_node_id(AstNode::kFunctionEntryId + 1);
Steve Block44f0eee2011-05-26 01:26:41 +0100536}
537
538
539LexicalScope::~LexicalScope() {
Steve Block44f0eee2011-05-26 01:26:41 +0100540 parser_->top_scope_ = previous_scope_;
541 parser_->lexical_scope_ = lexical_scope_parent_;
542 parser_->with_nesting_level_ = previous_with_nesting_level_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100543 parser_->isolate()->set_ast_node_id(previous_ast_node_id_);
Steve Block44f0eee2011-05-26 01:26:41 +0100544}
545
546
Steve Blocka7e24c12009-10-30 11:49:00 +0000547// ----------------------------------------------------------------------------
548// The CHECK_OK macro is a convenient macro to enforce error
549// handling for functions that may fail (by returning !*ok).
550//
551// CAUTION: This macro appends extra statements after a call,
552// thus it must never be used where only a single statement
553// is correct (e.g. an if statement branch w/o braces)!
554
555#define CHECK_OK ok); \
556 if (!*ok) return NULL; \
557 ((void)0
558#define DUMMY ) // to make indentation work
559#undef DUMMY
560
561#define CHECK_FAILED /**/); \
562 if (failed_) return NULL; \
563 ((void)0
564#define DUMMY ) // to make indentation work
565#undef DUMMY
566
567// ----------------------------------------------------------------------------
568// Implementation of Parser
569
570Parser::Parser(Handle<Script> script,
571 bool allow_natives_syntax,
572 v8::Extension* extension,
Steve Blocka7e24c12009-10-30 11:49:00 +0000573 ScriptDataImpl* pre_data)
Steve Block44f0eee2011-05-26 01:26:41 +0100574 : isolate_(script->GetIsolate()),
575 symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800576 script_(script),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100577 scanner_(isolate_->unicode_cache()),
Steve Blocka7e24c12009-10-30 11:49:00 +0000578 top_scope_(NULL),
579 with_nesting_level_(0),
Steve Block44f0eee2011-05-26 01:26:41 +0100580 lexical_scope_(NULL),
Steve Blocka7e24c12009-10-30 11:49:00 +0000581 target_stack_(NULL),
582 allow_natives_syntax_(allow_natives_syntax),
583 extension_(extension),
Steve Block6ded16b2010-05-10 14:33:55 +0100584 pre_data_(pre_data),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100585 fni_(NULL),
Ben Murdochb8e0da22011-05-16 14:20:40 +0100586 stack_overflow_(false),
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000587 parenthesized_function_(false),
588 harmony_block_scoping_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100589 AstNode::ResetIds();
Steve Blocka7e24c12009-10-30 11:49:00 +0000590}
591
592
Steve Blocka7e24c12009-10-30 11:49:00 +0000593FunctionLiteral* Parser::ParseProgram(Handle<String> source,
Steve Block1e0659c2011-05-24 12:43:12 +0100594 bool in_global_context,
595 StrictModeFlag strict_mode) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000596 ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
Steve Blocka7e24c12009-10-30 11:49:00 +0000597
Steve Block44f0eee2011-05-26 01:26:41 +0100598 HistogramTimerScope timer(isolate()->counters()->parse());
599 isolate()->counters()->total_parse_size()->Increment(source->length());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000600 fni_ = new(zone()) FuncNameInferrer(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000601
602 // Initialize parser state.
Steve Block6ded16b2010-05-10 14:33:55 +0100603 source->TryFlatten();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100604 if (source->IsExternalTwoByteString()) {
605 // Notice that the stream is destroyed at the end of the branch block.
606 // The last line of the blocks can't be moved outside, even though they're
607 // identical calls.
608 ExternalTwoByteStringUC16CharacterStream stream(
609 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100610 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100611 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100612 } else {
613 GenericStringUC16CharacterStream stream(source, 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100614 scanner_.Initialize(&stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100615 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100616 }
617}
618
619
620FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
621 bool in_global_context,
Steve Block1e0659c2011-05-24 12:43:12 +0100622 StrictModeFlag strict_mode,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100623 ZoneScope* zone_scope) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000624 ASSERT(target_stack_ == NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100625 if (pre_data_ != NULL) pre_data_->Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000626
627 // Compute the parsing mode.
628 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
629 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
630
631 Scope::Type type =
632 in_global_context
633 ? Scope::GLOBAL_SCOPE
634 : Scope::EVAL_SCOPE;
Steve Block44f0eee2011-05-26 01:26:41 +0100635 Handle<String> no_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000636
637 FunctionLiteral* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800638 { Scope* scope = NewScope(top_scope_, type, inside_with());
Steve Block44f0eee2011-05-26 01:26:41 +0100639 LexicalScope lexical_scope(this, scope, isolate());
Steve Block1e0659c2011-05-24 12:43:12 +0100640 if (strict_mode == kStrictMode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100641 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +0100642 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000643 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16);
Steve Blocka7e24c12009-10-30 11:49:00 +0000644 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100645 int beg_loc = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800646 ParseSourceElements(body, Token::EOS, &ok);
Steve Block44f0eee2011-05-26 01:26:41 +0100647 if (ok && top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +0100648 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
649 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000650 if (ok) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100651 result = new(zone()) FunctionLiteral(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000652 isolate(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000653 no_name,
654 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800655 body,
Steve Block44f0eee2011-05-26 01:26:41 +0100656 lexical_scope.materialized_literal_count(),
657 lexical_scope.expected_property_count(),
658 lexical_scope.only_simple_this_property_assignments(),
659 lexical_scope.this_property_assignments(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000660 0,
661 0,
662 source->length(),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000663 FunctionLiteral::ANONYMOUS_EXPRESSION,
664 false); // Does not have duplicate parameters.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100665 } else if (stack_overflow_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100666 isolate()->StackOverflow();
Steve Blocka7e24c12009-10-30 11:49:00 +0000667 }
668 }
669
670 // Make sure the target stack is empty.
671 ASSERT(target_stack_ == NULL);
672
673 // If there was a syntax error we have to get rid of the AST
674 // and it is not safe to do so before the scope has been deleted.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100675 if (result == NULL) zone_scope->DeleteOnExit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000676 return result;
677}
678
Steve Block44f0eee2011-05-26 01:26:41 +0100679FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000680 ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
Steve Block44f0eee2011-05-26 01:26:41 +0100681 HistogramTimerScope timer(isolate()->counters()->parse_lazy());
Ben Murdochf87a2032010-10-22 12:50:53 +0100682 Handle<String> source(String::cast(script_->source()));
Steve Block44f0eee2011-05-26 01:26:41 +0100683 isolate()->counters()->total_parse_size()->Increment(source->length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000684
Steve Block44f0eee2011-05-26 01:26:41 +0100685 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100686 // Initialize parser state.
687 source->TryFlatten();
688 if (source->IsExternalTwoByteString()) {
689 ExternalTwoByteStringUC16CharacterStream stream(
690 Handle<ExternalTwoByteString>::cast(source),
Steve Block44f0eee2011-05-26 01:26:41 +0100691 shared_info->start_position(),
692 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100693 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
694 return result;
695 } else {
696 GenericStringUC16CharacterStream stream(source,
Steve Block44f0eee2011-05-26 01:26:41 +0100697 shared_info->start_position(),
698 shared_info->end_position());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100699 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
700 return result;
701 }
702}
703
704
Steve Block44f0eee2011-05-26 01:26:41 +0100705FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100706 UC16CharacterStream* source,
707 ZoneScope* zone_scope) {
Steve Block44f0eee2011-05-26 01:26:41 +0100708 Handle<SharedFunctionInfo> shared_info = info->shared_info();
Steve Block9fac8402011-05-12 15:51:54 +0100709 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100710 ASSERT(target_stack_ == NULL);
711
Steve Block44f0eee2011-05-26 01:26:41 +0100712 Handle<String> name(String::cast(shared_info->name()));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000713 fni_ = new(zone()) FuncNameInferrer(isolate());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100714 fni_->PushEnclosingName(name);
715
Steve Blocka7e24c12009-10-30 11:49:00 +0000716 mode_ = PARSE_EAGERLY;
717
718 // Place holder for the result.
719 FunctionLiteral* result = NULL;
720
721 {
722 // Parse the function literal.
Steve Block44f0eee2011-05-26 01:26:41 +0100723 Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
724 if (!info->closure().is_null()) {
725 scope = Scope::DeserializeScopeChain(info, scope);
726 }
727 LexicalScope lexical_scope(this, scope, isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000728
Steve Block44f0eee2011-05-26 01:26:41 +0100729 if (shared_info->strict_mode()) {
730 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +0100731 }
732
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000733 FunctionLiteral::Type type = shared_info->is_expression()
734 ? (shared_info->is_anonymous()
735 ? FunctionLiteral::ANONYMOUS_EXPRESSION
736 : FunctionLiteral::NAMED_EXPRESSION)
737 : FunctionLiteral::DECLARATION;
Steve Blocka7e24c12009-10-30 11:49:00 +0000738 bool ok = true;
Steve Block1e0659c2011-05-24 12:43:12 +0100739 result = ParseFunctionLiteral(name,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000740 false, // Strict mode name already checked.
741 RelocInfo::kNoPosition,
742 type,
743 &ok);
Steve Blocka7e24c12009-10-30 11:49:00 +0000744 // Make sure the results agree.
745 ASSERT(ok == (result != NULL));
Steve Blocka7e24c12009-10-30 11:49:00 +0000746 }
747
748 // Make sure the target stack is empty.
749 ASSERT(target_stack_ == NULL);
750
751 // If there was a stack overflow we have to get rid of AST and it is
752 // not safe to do before scope has been deleted.
753 if (result == NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100754 zone_scope->DeleteOnExit();
Steve Block44f0eee2011-05-26 01:26:41 +0100755 if (stack_overflow_) isolate()->StackOverflow();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100756 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100757 Handle<String> inferred_name(shared_info->inferred_name());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100758 result->set_inferred_name(inferred_name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000759 }
760 return result;
761}
762
Ben Murdochf87a2032010-10-22 12:50:53 +0100763
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800764Handle<String> Parser::GetSymbol(bool* ok) {
765 int symbol_id = -1;
766 if (pre_data() != NULL) {
767 symbol_id = pre_data()->GetSymbolIdentifier();
Leon Clarke4515c472010-02-03 11:58:03 +0000768 }
Steve Block9fac8402011-05-12 15:51:54 +0100769 return LookupSymbol(symbol_id);
Leon Clarke4515c472010-02-03 11:58:03 +0000770}
Steve Blocka7e24c12009-10-30 11:49:00 +0000771
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800772
Steve Blocka7e24c12009-10-30 11:49:00 +0000773void Parser::ReportMessage(const char* type, Vector<const char*> args) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100774 Scanner::Location source_location = scanner().location();
Steve Blocka7e24c12009-10-30 11:49:00 +0000775 ReportMessageAt(source_location, type, args);
776}
777
778
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800779void Parser::ReportMessageAt(Scanner::Location source_location,
780 const char* type,
781 Vector<const char*> args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000782 MessageLocation location(script_,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100783 source_location.beg_pos,
784 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100785 Factory* factory = isolate()->factory();
786 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000787 for (int i = 0; i < args.length(); i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100788 Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100789 elements->set(i, *arg_string);
Steve Blocka7e24c12009-10-30 11:49:00 +0000790 }
Steve Block44f0eee2011-05-26 01:26:41 +0100791 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
792 Handle<Object> result = factory->NewSyntaxError(type, array);
793 isolate()->Throw(*result, &location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000794}
795
796
Ben Murdochb8e0da22011-05-16 14:20:40 +0100797void Parser::ReportMessageAt(Scanner::Location source_location,
798 const char* type,
799 Vector<Handle<String> > args) {
800 MessageLocation location(script_,
801 source_location.beg_pos,
802 source_location.end_pos);
Steve Block44f0eee2011-05-26 01:26:41 +0100803 Factory* factory = isolate()->factory();
804 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100805 for (int i = 0; i < args.length(); i++) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100806 elements->set(i, *args[i]);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100807 }
Steve Block44f0eee2011-05-26 01:26:41 +0100808 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
809 Handle<Object> result = factory->NewSyntaxError(type, array);
810 isolate()->Throw(*result, &location);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100811}
812
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000813void Parser::SetHarmonyBlockScoping(bool block_scoping) {
814 scanner().SetHarmonyBlockScoping(block_scoping);
815 harmony_block_scoping_ = block_scoping;
816}
Ben Murdochb8e0da22011-05-16 14:20:40 +0100817
Steve Blocka7e24c12009-10-30 11:49:00 +0000818// Base class containing common code for the different finder classes used by
819// the parser.
820class ParserFinder {
821 protected:
822 ParserFinder() {}
823 static Assignment* AsAssignment(Statement* stat) {
824 if (stat == NULL) return NULL;
825 ExpressionStatement* exp_stat = stat->AsExpressionStatement();
826 if (exp_stat == NULL) return NULL;
827 return exp_stat->expression()->AsAssignment();
828 }
829};
830
831
832// An InitializationBlockFinder finds and marks sequences of statements of the
Steve Blockd0582a62009-12-15 09:54:21 +0000833// form expr.a = ...; expr.b = ...; etc.
Steve Blocka7e24c12009-10-30 11:49:00 +0000834class InitializationBlockFinder : public ParserFinder {
835 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000836 // We find and mark the initialization blocks in top level
837 // non-looping code only. This is because the optimization prevents
838 // reuse of the map transitions, so it should be used only for code
839 // that will only be run once.
840 InitializationBlockFinder(Scope* top_scope, Target* target)
841 : enabled_(top_scope->DeclarationScope()->is_global_scope() &&
842 !IsLoopTarget(target)),
843 first_in_block_(NULL),
844 last_in_block_(NULL),
845 block_size_(0) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000846
847 ~InitializationBlockFinder() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000848 if (!enabled_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000849 if (InBlock()) EndBlock();
850 }
851
852 void Update(Statement* stat) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000853 if (!enabled_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000854 Assignment* assignment = AsAssignment(stat);
855 if (InBlock()) {
856 if (BlockContinues(assignment)) {
857 UpdateBlock(assignment);
858 } else {
859 EndBlock();
860 }
861 }
862 if (!InBlock() && (assignment != NULL) &&
863 (assignment->op() == Token::ASSIGN)) {
864 StartBlock(assignment);
865 }
866 }
867
868 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800869 // The minimum number of contiguous assignment that will
870 // be treated as an initialization block. Benchmarks show that
871 // the overhead exceeds the savings below this limit.
872 static const int kMinInitializationBlock = 3;
873
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000874 static bool IsLoopTarget(Target* target) {
875 while (target != NULL) {
876 if (target->node()->AsIterationStatement() != NULL) return true;
877 target = target->previous();
878 }
879 return false;
880 }
881
Steve Blocka7e24c12009-10-30 11:49:00 +0000882 // Returns true if the expressions appear to denote the same object.
883 // In the context of initialization blocks, we only consider expressions
Steve Blockd0582a62009-12-15 09:54:21 +0000884 // of the form 'expr.x' or expr["x"].
Steve Blocka7e24c12009-10-30 11:49:00 +0000885 static bool SameObject(Expression* e1, Expression* e2) {
886 VariableProxy* v1 = e1->AsVariableProxy();
887 VariableProxy* v2 = e2->AsVariableProxy();
888 if (v1 != NULL && v2 != NULL) {
889 return v1->name()->Equals(*v2->name());
890 }
891 Property* p1 = e1->AsProperty();
892 Property* p2 = e2->AsProperty();
893 if ((p1 == NULL) || (p2 == NULL)) return false;
894 Literal* key1 = p1->key()->AsLiteral();
895 Literal* key2 = p2->key()->AsLiteral();
896 if ((key1 == NULL) || (key2 == NULL)) return false;
897 if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
898 return false;
899 }
900 String* name1 = String::cast(*key1->handle());
901 String* name2 = String::cast(*key2->handle());
902 if (!name1->Equals(name2)) return false;
903 return SameObject(p1->obj(), p2->obj());
904 }
905
906 // Returns true if the expressions appear to denote different properties
907 // of the same object.
908 static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
909 Property* p1 = e1->AsProperty();
910 Property* p2 = e2->AsProperty();
911 if ((p1 == NULL) || (p2 == NULL)) return false;
912 return SameObject(p1->obj(), p2->obj());
913 }
914
915 bool BlockContinues(Assignment* assignment) {
916 if ((assignment == NULL) || (first_in_block_ == NULL)) return false;
917 if (assignment->op() != Token::ASSIGN) return false;
918 return PropertyOfSameObject(first_in_block_->target(),
919 assignment->target());
920 }
921
922 void StartBlock(Assignment* assignment) {
923 first_in_block_ = assignment;
924 last_in_block_ = assignment;
925 block_size_ = 1;
926 }
927
928 void UpdateBlock(Assignment* assignment) {
929 last_in_block_ = assignment;
930 ++block_size_;
931 }
932
933 void EndBlock() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800934 if (block_size_ >= kMinInitializationBlock) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000935 first_in_block_->mark_block_start();
936 last_in_block_->mark_block_end();
937 }
938 last_in_block_ = first_in_block_ = NULL;
939 block_size_ = 0;
940 }
941
942 bool InBlock() { return first_in_block_ != NULL; }
943
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000944 const bool enabled_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000945 Assignment* first_in_block_;
946 Assignment* last_in_block_;
947 int block_size_;
948
949 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
950};
951
952
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000953// A ThisNamedPropertyAssignmentFinder finds and marks statements of the form
Steve Blocka7e24c12009-10-30 11:49:00 +0000954// this.x = ...;, where x is a named property. It also determines whether a
955// function contains only assignments of this type.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000956class ThisNamedPropertyAssignmentFinder : public ParserFinder {
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000958 explicit ThisNamedPropertyAssignmentFinder(Isolate* isolate)
Steve Block44f0eee2011-05-26 01:26:41 +0100959 : isolate_(isolate),
960 only_simple_this_property_assignments_(true),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000961 names_(0),
962 assigned_arguments_(0),
963 assigned_constants_(0) {
964 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000965
966 void Update(Scope* scope, Statement* stat) {
Steve Blockd0582a62009-12-15 09:54:21 +0000967 // Bail out if function already has property assignment that are
968 // not simple this property assignments.
969 if (!only_simple_this_property_assignments_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000970 return;
971 }
972
973 // Check whether this statement is of the form this.x = ...;
974 Assignment* assignment = AsAssignment(stat);
975 if (IsThisPropertyAssignment(assignment)) {
976 HandleThisPropertyAssignment(scope, assignment);
977 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +0000978 only_simple_this_property_assignments_ = false;
979 }
980 }
981
Steve Blocka7e24c12009-10-30 11:49:00 +0000982 // Returns whether only statements of the form this.x = y; where y is either a
983 // constant or a function argument was encountered.
984 bool only_simple_this_property_assignments() {
985 return only_simple_this_property_assignments_;
986 }
987
988 // Returns a fixed array containing three elements for each assignment of the
989 // form this.x = y;
990 Handle<FixedArray> GetThisPropertyAssignments() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000991 if (names_.is_empty()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100992 return isolate_->factory()->empty_fixed_array();
Steve Blocka7e24c12009-10-30 11:49:00 +0000993 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000994 ASSERT_EQ(names_.length(), assigned_arguments_.length());
995 ASSERT_EQ(names_.length(), assigned_constants_.length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000996 Handle<FixedArray> assignments =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000997 isolate_->factory()->NewFixedArray(names_.length() * 3);
998 for (int i = 0; i < names_.length(); ++i) {
999 assignments->set(i * 3, *names_[i]);
1000 assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_[i]));
1001 assignments->set(i * 3 + 2, *assigned_constants_[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001002 }
1003 return assignments;
1004 }
1005
1006 private:
1007 bool IsThisPropertyAssignment(Assignment* assignment) {
1008 if (assignment != NULL) {
1009 Property* property = assignment->target()->AsProperty();
1010 return assignment->op() == Token::ASSIGN
1011 && property != NULL
1012 && property->obj()->AsVariableProxy() != NULL
1013 && property->obj()->AsVariableProxy()->is_this();
1014 }
1015 return false;
1016 }
1017
1018 void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
Steve Block6ded16b2010-05-10 14:33:55 +01001019 // Check that the property assigned to is a named property, which is not
1020 // __proto__.
Steve Blocka7e24c12009-10-30 11:49:00 +00001021 Property* property = assignment->target()->AsProperty();
1022 ASSERT(property != NULL);
1023 Literal* literal = property->key()->AsLiteral();
1024 uint32_t dummy;
1025 if (literal != NULL &&
1026 literal->handle()->IsString() &&
Steve Block44f0eee2011-05-26 01:26:41 +01001027 !String::cast(*(literal->handle()))->Equals(
1028 isolate_->heap()->Proto_symbol()) &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001029 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
1030 Handle<String> key = Handle<String>::cast(literal->handle());
1031
1032 // Check whether the value assigned is either a constant or matches the
1033 // name of one of the arguments to the function.
1034 if (assignment->value()->AsLiteral() != NULL) {
1035 // Constant assigned.
1036 Literal* literal = assignment->value()->AsLiteral();
1037 AssignmentFromConstant(key, literal->handle());
Steve Blockd0582a62009-12-15 09:54:21 +00001038 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001039 } else if (assignment->value()->AsVariableProxy() != NULL) {
1040 // Variable assigned.
1041 Handle<String> name =
1042 assignment->value()->AsVariableProxy()->name();
1043 // Check whether the variable assigned matches an argument name.
Steve Blocka7e24c12009-10-30 11:49:00 +00001044 for (int i = 0; i < scope->num_parameters(); i++) {
1045 if (*scope->parameter(i)->name() == *name) {
1046 // Assigned from function argument.
Steve Blockd0582a62009-12-15 09:54:21 +00001047 AssignmentFromParameter(key, i);
1048 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001049 }
1050 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001051 }
1052 }
Steve Blockd0582a62009-12-15 09:54:21 +00001053 // It is not a simple "this.x = value;" assignment with a constant
1054 // or parameter value.
1055 AssignmentFromSomethingElse();
Steve Blocka7e24c12009-10-30 11:49:00 +00001056 }
1057
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001058
1059
1060
1061 // We will potentially reorder the property assignments, so they must be
1062 // simple enough that the ordering does not matter.
Steve Blocka7e24c12009-10-30 11:49:00 +00001063 void AssignmentFromParameter(Handle<String> name, int index) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001064 EnsureInitialized();
1065 for (int i = 0; i < names_.length(); ++i) {
1066 if (name->Equals(*names_[i])) {
1067 assigned_arguments_[i] = index;
1068 assigned_constants_[i] = isolate_->factory()->undefined_value();
1069 return;
1070 }
1071 }
1072 names_.Add(name);
1073 assigned_arguments_.Add(index);
1074 assigned_constants_.Add(isolate_->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001075 }
1076
1077 void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001078 EnsureInitialized();
1079 for (int i = 0; i < names_.length(); ++i) {
1080 if (name->Equals(*names_[i])) {
1081 assigned_arguments_[i] = -1;
1082 assigned_constants_[i] = value;
1083 return;
1084 }
1085 }
1086 names_.Add(name);
1087 assigned_arguments_.Add(-1);
1088 assigned_constants_.Add(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001089 }
1090
Steve Blockd0582a62009-12-15 09:54:21 +00001091 void AssignmentFromSomethingElse() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001092 // The this assignment is not a simple one.
1093 only_simple_this_property_assignments_ = false;
1094 }
1095
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001096 void EnsureInitialized() {
1097 if (names_.capacity() == 0) {
1098 ASSERT(assigned_arguments_.capacity() == 0);
1099 ASSERT(assigned_constants_.capacity() == 0);
1100 names_.Initialize(4);
1101 assigned_arguments_.Initialize(4);
1102 assigned_constants_.Initialize(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001103 }
1104 }
1105
Steve Block44f0eee2011-05-26 01:26:41 +01001106 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001107 bool only_simple_this_property_assignments_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001108 ZoneStringList names_;
1109 ZoneList<int> assigned_arguments_;
1110 ZoneObjectList assigned_constants_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001111};
1112
1113
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001114Statement* Parser::ParseSourceElement(ZoneStringList* labels,
1115 bool* ok) {
1116 if (peek() == Token::FUNCTION) {
1117 // FunctionDeclaration is only allowed in the context of SourceElements
1118 // (Ecma 262 5th Edition, clause 14):
1119 // SourceElement:
1120 // Statement
1121 // FunctionDeclaration
1122 // Common language extension is to allow function declaration in place
1123 // of any statement. This language extension is disabled in strict mode.
1124 return ParseFunctionDeclaration(ok);
1125 } else if (peek() == Token::LET) {
1126 return ParseVariableStatement(kSourceElement, ok);
1127 } else {
1128 return ParseStatement(labels, ok);
1129 }
1130}
1131
1132
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001133void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
Steve Blocka7e24c12009-10-30 11:49:00 +00001134 int end_token,
1135 bool* ok) {
1136 // SourceElements ::
1137 // (Statement)* <end_token>
1138
1139 // Allocate a target stack to use for this set of source
1140 // elements. This way, all scripts and functions get their own
1141 // target stack thus avoiding illegal breaks and continues across
1142 // functions.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001143 TargetScope scope(&this->target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001144
1145 ASSERT(processor != NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001146 InitializationBlockFinder block_finder(top_scope_, target_stack_);
1147 ThisNamedPropertyAssignmentFinder this_property_assignment_finder(isolate());
Steve Block1e0659c2011-05-24 12:43:12 +01001148 bool directive_prologue = true; // Parsing directive prologue.
1149
Steve Blocka7e24c12009-10-30 11:49:00 +00001150 while (peek() != end_token) {
Steve Block1e0659c2011-05-24 12:43:12 +01001151 if (directive_prologue && peek() != Token::STRING) {
1152 directive_prologue = false;
1153 }
1154
1155 Scanner::Location token_loc = scanner().peek_location();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001156 Statement* stat = ParseSourceElement(NULL, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01001157 if (stat == NULL || stat->IsEmpty()) {
1158 directive_prologue = false; // End of directive prologue.
1159 continue;
1160 }
1161
1162 if (directive_prologue) {
1163 // A shot at a directive.
1164 ExpressionStatement *e_stat;
1165 Literal *literal;
1166 // Still processing directive prologue?
1167 if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1168 (literal = e_stat->expression()->AsLiteral()) != NULL &&
1169 literal->handle()->IsString()) {
1170 Handle<String> directive = Handle<String>::cast(literal->handle());
1171
1172 // Check "use strict" directive (ES5 14.1).
Steve Block44f0eee2011-05-26 01:26:41 +01001173 if (!top_scope_->is_strict_mode() &&
1174 directive->Equals(isolate()->heap()->use_strict()) &&
Steve Block1e0659c2011-05-24 12:43:12 +01001175 token_loc.end_pos - token_loc.beg_pos ==
Steve Block44f0eee2011-05-26 01:26:41 +01001176 isolate()->heap()->use_strict()->length() + 2) {
1177 top_scope_->EnableStrictMode();
Steve Block1e0659c2011-05-24 12:43:12 +01001178 // "use strict" is the only directive for now.
1179 directive_prologue = false;
1180 }
1181 } else {
1182 // End of the directive prologue.
1183 directive_prologue = false;
1184 }
1185 }
1186
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001187 block_finder.Update(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00001188 // Find and mark all assignments to named properties in this (this.x =)
1189 if (top_scope_->is_function_scope()) {
1190 this_property_assignment_finder.Update(top_scope_, stat);
1191 }
1192 processor->Add(stat);
1193 }
1194
1195 // Propagate the collected information on this property assignments.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001196 if (top_scope_->is_function_scope()) {
Steve Blockd0582a62009-12-15 09:54:21 +00001197 bool only_simple_this_property_assignments =
Andrei Popescu402d9372010-02-26 13:31:12 +00001198 this_property_assignment_finder.only_simple_this_property_assignments()
1199 && top_scope_->declarations()->length() == 0;
Steve Blockd0582a62009-12-15 09:54:21 +00001200 if (only_simple_this_property_assignments) {
Steve Block44f0eee2011-05-26 01:26:41 +01001201 lexical_scope_->SetThisPropertyAssignmentInfo(
Steve Blockd0582a62009-12-15 09:54:21 +00001202 only_simple_this_property_assignments,
Steve Blocka7e24c12009-10-30 11:49:00 +00001203 this_property_assignment_finder.GetThisPropertyAssignments());
1204 }
1205 }
1206 return 0;
1207}
1208
1209
1210Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1211 // Statement ::
1212 // Block
1213 // VariableStatement
1214 // EmptyStatement
1215 // ExpressionStatement
1216 // IfStatement
1217 // IterationStatement
1218 // ContinueStatement
1219 // BreakStatement
1220 // ReturnStatement
1221 // WithStatement
1222 // LabelledStatement
1223 // SwitchStatement
1224 // ThrowStatement
1225 // TryStatement
1226 // DebuggerStatement
1227
1228 // Note: Since labels can only be used by 'break' and 'continue'
1229 // statements, which themselves are only valid within blocks,
1230 // iterations or 'switch' statements (i.e., BreakableStatements),
1231 // labels can be simply ignored in all other cases; except for
1232 // trivial labeled break statements 'label: break label' which is
1233 // parsed into an empty statement.
1234
1235 // Keep the source position of the statement
1236 int statement_pos = scanner().peek_location().beg_pos;
1237 Statement* stmt = NULL;
1238 switch (peek()) {
1239 case Token::LBRACE:
1240 return ParseBlock(labels, ok);
1241
1242 case Token::CONST: // fall through
1243 case Token::VAR:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001244 stmt = ParseVariableStatement(kStatement, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001245 break;
1246
1247 case Token::SEMICOLON:
1248 Next();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001249 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001250
1251 case Token::IF:
1252 stmt = ParseIfStatement(labels, ok);
1253 break;
1254
1255 case Token::DO:
Steve Block3ce2e202009-11-05 08:53:23 +00001256 stmt = ParseDoWhileStatement(labels, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001257 break;
1258
1259 case Token::WHILE:
1260 stmt = ParseWhileStatement(labels, ok);
1261 break;
1262
1263 case Token::FOR:
1264 stmt = ParseForStatement(labels, ok);
1265 break;
1266
1267 case Token::CONTINUE:
1268 stmt = ParseContinueStatement(ok);
1269 break;
1270
1271 case Token::BREAK:
1272 stmt = ParseBreakStatement(labels, ok);
1273 break;
1274
1275 case Token::RETURN:
1276 stmt = ParseReturnStatement(ok);
1277 break;
1278
1279 case Token::WITH:
1280 stmt = ParseWithStatement(labels, ok);
1281 break;
1282
1283 case Token::SWITCH:
1284 stmt = ParseSwitchStatement(labels, ok);
1285 break;
1286
1287 case Token::THROW:
1288 stmt = ParseThrowStatement(ok);
1289 break;
1290
1291 case Token::TRY: {
1292 // NOTE: It is somewhat complicated to have labels on
1293 // try-statements. When breaking out of a try-finally statement,
1294 // one must take great care not to treat it as a
1295 // fall-through. It is much easier just to wrap the entire
1296 // try-statement in a statement block and put the labels there
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001297 Block* result = new(zone()) Block(isolate(), labels, 1, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001298 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001299 TryStatement* statement = ParseTryStatement(CHECK_OK);
1300 if (statement) {
1301 statement->set_statement_pos(statement_pos);
1302 }
1303 if (result) result->AddStatement(statement);
1304 return result;
1305 }
1306
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001307 case Token::FUNCTION: {
1308 // In strict mode, FunctionDeclaration is only allowed in the context
1309 // of SourceElements.
Steve Block44f0eee2011-05-26 01:26:41 +01001310 if (top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001311 ReportMessageAt(scanner().peek_location(), "strict_function",
1312 Vector<const char*>::empty());
1313 *ok = false;
1314 return NULL;
1315 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001316 return ParseFunctionDeclaration(ok);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001317 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001318
Steve Blocka7e24c12009-10-30 11:49:00 +00001319 case Token::DEBUGGER:
1320 stmt = ParseDebuggerStatement(ok);
1321 break;
1322
1323 default:
1324 stmt = ParseExpressionOrLabelledStatement(labels, ok);
1325 }
1326
1327 // Store the source position of the statement
1328 if (stmt != NULL) stmt->set_statement_pos(statement_pos);
1329 return stmt;
1330}
1331
1332
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001333VariableProxy* Parser::Declare(Handle<String> name,
1334 Variable::Mode mode,
1335 FunctionLiteral* fun,
1336 bool resolve,
1337 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001338 Variable* var = NULL;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001339 // If we are inside a function, a declaration of a var/const variable is a
1340 // truly local variable, and the scope of the variable is always the function
1341 // scope.
Steve Blocka7e24c12009-10-30 11:49:00 +00001342
1343 // If a function scope exists, then we can statically declare this
1344 // variable and also set its mode. In any case, a Declaration node
1345 // will be added to the scope so that the declaration can be added
1346 // to the corresponding activation frame at runtime if necessary.
1347 // For instance declarations inside an eval scope need to be added
1348 // to the calling function context.
Ben Murdoch257744e2011-11-30 15:57:28 +00001349 // Similarly, strict mode eval scope does not leak variable declarations to
1350 // the caller's scope so we declare all locals, too.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001351
1352 Scope* declaration_scope = mode == Variable::LET ? top_scope_
1353 : top_scope_->DeclarationScope();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001354 if (declaration_scope->is_function_scope() ||
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001355 declaration_scope->is_strict_mode_eval_scope() ||
1356 declaration_scope->is_block_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001357 // Declare the variable in the function scope.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001358 var = declaration_scope->LocalLookup(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001359 if (var == NULL) {
1360 // Declare the name.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001361 var = declaration_scope->DeclareLocal(name, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001362 } else {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001363 // The name was declared before; check for conflicting re-declarations.
1364 // We have a conflict if either of the declarations is not a var. There
1365 // is similar code in runtime.cc in the Declare functions.
1366 if ((mode != Variable::VAR) || (var->mode() != Variable::VAR)) {
1367 // We only have vars, consts and lets in declarations.
Steve Blocka7e24c12009-10-30 11:49:00 +00001368 ASSERT(var->mode() == Variable::VAR ||
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001369 var->mode() == Variable::CONST ||
1370 var->mode() == Variable::LET);
1371 const char* type = (var->mode() == Variable::VAR) ? "var" :
1372 (var->mode() == Variable::CONST) ? "const" : "let";
Steve Blocka7e24c12009-10-30 11:49:00 +00001373 Handle<String> type_string =
Steve Block44f0eee2011-05-26 01:26:41 +01001374 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00001375 Expression* expression =
Steve Block44f0eee2011-05-26 01:26:41 +01001376 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00001377 type_string, name);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001378 declaration_scope->SetIllegalRedeclaration(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00001379 }
1380 }
1381 }
1382
1383 // We add a declaration node for every declaration. The compiler
1384 // will only generate code if necessary. In particular, declarations
1385 // for inner local variables that do not represent functions won't
1386 // result in any generated code.
1387 //
1388 // Note that we always add an unresolved proxy even if it's not
1389 // used, simply because we don't know in this method (w/o extra
1390 // parameters) if the proxy is needed or not. The proxy will be
1391 // bound during variable resolution time unless it was pre-bound
1392 // below.
1393 //
1394 // WARNING: This will lead to multiple declaration nodes for the
1395 // same variable if it is declared several times. This is not a
1396 // semantic issue as long as we keep the source order, but it may be
1397 // a performance issue since it may lead to repeated
1398 // Runtime::DeclareContextSlot() calls.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001399 VariableProxy* proxy = declaration_scope->NewUnresolved(name, false);
1400 declaration_scope->AddDeclaration(new(zone()) Declaration(proxy, mode, fun));
Steve Blocka7e24c12009-10-30 11:49:00 +00001401
1402 // For global const variables we bind the proxy to a variable.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001403 if (mode == Variable::CONST && declaration_scope->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001404 ASSERT(resolve); // should be set by all callers
1405 Variable::Kind kind = Variable::NORMAL;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001406 var = new(zone()) Variable(declaration_scope,
1407 name,
1408 Variable::CONST,
1409 true,
1410 kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001411 }
1412
1413 // If requested and we have a local variable, bind the proxy to the variable
1414 // at parse-time. This is used for functions (and consts) declared inside
1415 // statements: the corresponding function (or const) variable must be in the
1416 // function scope and not a statement-local scope, e.g. as provided with a
1417 // 'with' statement:
1418 //
1419 // with (obj) {
1420 // function f() {}
1421 // }
1422 //
1423 // which is translated into:
1424 //
1425 // with (obj) {
1426 // // in this case this is not: 'var f; f = function () {};'
1427 // var f = function () {};
1428 // }
1429 //
1430 // Note that if 'f' is accessed from inside the 'with' statement, it
1431 // will be allocated in the context (because we must be able to look
1432 // it up dynamically) but it will also be accessed statically, i.e.,
1433 // with a context slot index and a context chain length for this
1434 // initialization code. Thus, inside the 'with' statement, we need
1435 // both access to the static and the dynamic context chain; the
1436 // runtime needs to provide both.
1437 if (resolve && var != NULL) proxy->BindTo(var);
1438
1439 return proxy;
1440}
1441
1442
1443// Language extension which is only enabled for source files loaded
1444// through the API's extension mechanism. A native function
1445// declaration is resolved by looking up the function through a
1446// callback provided by the extension.
1447Statement* Parser::ParseNativeDeclaration(bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001448 Expect(Token::FUNCTION, CHECK_OK);
1449 Handle<String> name = ParseIdentifier(CHECK_OK);
1450 Expect(Token::LPAREN, CHECK_OK);
1451 bool done = (peek() == Token::RPAREN);
1452 while (!done) {
1453 ParseIdentifier(CHECK_OK);
1454 done = (peek() == Token::RPAREN);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001455 if (!done) {
1456 Expect(Token::COMMA, CHECK_OK);
1457 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001458 }
1459 Expect(Token::RPAREN, CHECK_OK);
1460 Expect(Token::SEMICOLON, CHECK_OK);
1461
Steve Blocka7e24c12009-10-30 11:49:00 +00001462 // Make sure that the function containing the native declaration
1463 // isn't lazily compiled. The extension structures are only
1464 // accessible while parsing the first time not when reparsing
1465 // because of lazy compilation.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001466 top_scope_->DeclarationScope()->ForceEagerCompilation();
Steve Blocka7e24c12009-10-30 11:49:00 +00001467
1468 // Compute the function template for the native function.
1469 v8::Handle<v8::FunctionTemplate> fun_template =
1470 extension_->GetNativeFunction(v8::Utils::ToLocal(name));
1471 ASSERT(!fun_template.IsEmpty());
1472
Steve Block6ded16b2010-05-10 14:33:55 +01001473 // Instantiate the function and create a shared function info from it.
Steve Blocka7e24c12009-10-30 11:49:00 +00001474 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1475 const int literals = fun->NumberOfLiterals();
1476 Handle<Code> code = Handle<Code>(fun->shared()->code());
Leon Clarkee46be812010-01-19 14:06:41 +00001477 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
Steve Block6ded16b2010-05-10 14:33:55 +01001478 Handle<SharedFunctionInfo> shared =
Steve Block44f0eee2011-05-26 01:26:41 +01001479 isolate()->factory()->NewSharedFunctionInfo(name, literals, code,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001480 Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
Steve Block6ded16b2010-05-10 14:33:55 +01001481 shared->set_construct_stub(*construct_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +00001482
Steve Block6ded16b2010-05-10 14:33:55 +01001483 // Copy the function data to the shared function info.
1484 shared->set_function_data(fun->shared()->function_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00001485 int parameters = fun->shared()->formal_parameter_count();
Steve Block6ded16b2010-05-10 14:33:55 +01001486 shared->set_formal_parameter_count(parameters);
Steve Blocka7e24c12009-10-30 11:49:00 +00001487
1488 // TODO(1240846): It's weird that native function declarations are
1489 // introduced dynamically when we meet their declarations, whereas
1490 // other functions are setup when entering the surrounding scope.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001491 SharedFunctionInfoLiteral* lit =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001492 new(zone()) SharedFunctionInfoLiteral(isolate(), shared);
Steve Blocka7e24c12009-10-30 11:49:00 +00001493 VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001494 return new(zone()) ExpressionStatement(new(zone()) Assignment(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001495 isolate(), Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
Steve Blocka7e24c12009-10-30 11:49:00 +00001496}
1497
1498
1499Statement* Parser::ParseFunctionDeclaration(bool* ok) {
1500 // FunctionDeclaration ::
1501 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1502 Expect(Token::FUNCTION, CHECK_OK);
1503 int function_token_position = scanner().location().beg_pos;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001504 bool is_strict_reserved = false;
1505 Handle<String> name = ParseIdentifierOrStrictReservedWord(
1506 &is_strict_reserved, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001507 FunctionLiteral* fun = ParseFunctionLiteral(name,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001508 is_strict_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00001509 function_token_position,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001510 FunctionLiteral::DECLARATION,
Steve Blocka7e24c12009-10-30 11:49:00 +00001511 CHECK_OK);
1512 // Even if we're not at the top-level of the global or a function
1513 // scope, we treat is as such and introduce the function with it's
1514 // initial value upon entering the corresponding scope.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001515 Variable::Mode mode = harmony_block_scoping_ ? Variable::LET : Variable::VAR;
1516 Declare(name, mode, fun, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001517 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001518}
1519
1520
1521Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001522 if (harmony_block_scoping_) return ParseScopedBlock(labels, ok);
1523
Steve Blocka7e24c12009-10-30 11:49:00 +00001524 // Block ::
1525 // '{' Statement* '}'
1526
1527 // Note that a Block does not introduce a new execution scope!
1528 // (ECMA-262, 3rd, 12.2)
1529 //
1530 // Construct block expecting 16 statements.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001531 Block* result = new(zone()) Block(isolate(), labels, 16, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001532 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001533 Expect(Token::LBRACE, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001534 InitializationBlockFinder block_finder(top_scope_, target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001535 while (peek() != Token::RBRACE) {
1536 Statement* stat = ParseStatement(NULL, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001537 if (stat && !stat->IsEmpty()) {
1538 result->AddStatement(stat);
1539 block_finder.Update(stat);
1540 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001541 }
1542 Expect(Token::RBRACE, CHECK_OK);
1543 return result;
1544}
1545
1546
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001547Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
1548 // Construct block expecting 16 statements.
1549 Block* body = new(zone()) Block(isolate(), labels, 16, false);
1550 Scope* saved_scope = top_scope_;
1551 Scope* block_scope = NewScope(top_scope_,
1552 Scope::BLOCK_SCOPE,
1553 inside_with());
1554 body->set_block_scope(block_scope);
1555 block_scope->DeclareLocal(isolate()->factory()->block_scope_symbol(),
1556 Variable::VAR);
1557 if (top_scope_->is_strict_mode()) {
1558 block_scope->EnableStrictMode();
1559 }
1560 top_scope_ = block_scope;
1561
1562 // Parse the statements and collect escaping labels.
1563 TargetCollector collector;
1564 Target target(&this->target_stack_, &collector);
1565 Expect(Token::LBRACE, CHECK_OK);
1566 {
1567 Target target_body(&this->target_stack_, body);
1568 InitializationBlockFinder block_finder(top_scope_, target_stack_);
1569
1570 while (peek() != Token::RBRACE) {
1571 Statement* stat = ParseSourceElement(NULL, CHECK_OK);
1572 if (stat && !stat->IsEmpty()) {
1573 body->AddStatement(stat);
1574 block_finder.Update(stat);
1575 }
1576 }
1577 }
1578 Expect(Token::RBRACE, CHECK_OK);
1579
1580 // Create exit block.
1581 Block* exit = new(zone()) Block(isolate(), NULL, 1, false);
1582 exit->AddStatement(new(zone()) ExitContextStatement());
1583
1584 // Create a try-finally statement.
1585 TryFinallyStatement* try_finally =
1586 new(zone()) TryFinallyStatement(body, exit);
1587 try_finally->set_escaping_targets(collector.targets());
1588 top_scope_ = saved_scope;
1589
1590 // Create a result block.
1591 Block* result = new(zone()) Block(isolate(), NULL, 1, false);
1592 result->AddStatement(try_finally);
1593 return result;
1594}
1595
1596
1597Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
1598 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001599 // VariableStatement ::
1600 // VariableDeclarations ';'
1601
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001602 Handle<String> ignore;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001603 Block* result = ParseVariableDeclarations(var_context,
1604 &ignore,
1605 CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001606 ExpectSemicolon(CHECK_OK);
1607 return result;
1608}
1609
Steve Block44f0eee2011-05-26 01:26:41 +01001610
1611bool Parser::IsEvalOrArguments(Handle<String> string) {
1612 return string.is_identical_to(isolate()->factory()->eval_symbol()) ||
1613 string.is_identical_to(isolate()->factory()->arguments_symbol());
Steve Block1e0659c2011-05-24 12:43:12 +01001614}
Steve Blocka7e24c12009-10-30 11:49:00 +00001615
Steve Block44f0eee2011-05-26 01:26:41 +01001616
Steve Blocka7e24c12009-10-30 11:49:00 +00001617// If the variable declaration declares exactly one non-const
1618// variable, then *var is set to that variable. In all other cases,
1619// *var is untouched; in particular, it is the caller's responsibility
1620// to initialize it properly. This mechanism is used for the parsing
1621// of 'for-in' loops.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001622Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001623 Handle<String>* out,
Steve Blocka7e24c12009-10-30 11:49:00 +00001624 bool* ok) {
1625 // VariableDeclarations ::
1626 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
1627
1628 Variable::Mode mode = Variable::VAR;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001629 // True if the binding needs initialization. 'let' and 'const' declared
1630 // bindings are created uninitialized by their declaration nodes and
1631 // need initialization. 'var' declared bindings are always initialized
1632 // immediately by their declaration nodes.
1633 bool needs_init = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001634 bool is_const = false;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001635 Token::Value init_op = Token::INIT_VAR;
Steve Blocka7e24c12009-10-30 11:49:00 +00001636 if (peek() == Token::VAR) {
1637 Consume(Token::VAR);
1638 } else if (peek() == Token::CONST) {
1639 Consume(Token::CONST);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001640 if (top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001641 ReportMessage("strict_const", Vector<const char*>::empty());
1642 *ok = false;
1643 return NULL;
1644 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001645 mode = Variable::CONST;
1646 is_const = true;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001647 needs_init = true;
1648 init_op = Token::INIT_CONST;
1649 } else if (peek() == Token::LET) {
1650 Consume(Token::LET);
1651 if (var_context != kSourceElement &&
1652 var_context != kForStatement) {
1653 ASSERT(var_context == kStatement);
1654 ReportMessage("unprotected_let", Vector<const char*>::empty());
1655 *ok = false;
1656 return NULL;
1657 }
1658 mode = Variable::LET;
1659 needs_init = true;
1660 init_op = Token::INIT_LET;
Steve Blocka7e24c12009-10-30 11:49:00 +00001661 } else {
1662 UNREACHABLE(); // by current callers
1663 }
1664
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001665 Scope* declaration_scope = mode == Variable::LET
1666 ? top_scope_ : top_scope_->DeclarationScope();
1667 // The scope of a var/const declared variable anywhere inside a function
Steve Blocka7e24c12009-10-30 11:49:00 +00001668 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001669 // transform a source-level var/const declaration into a (Function)
Steve Blocka7e24c12009-10-30 11:49:00 +00001670 // Scope declaration, and rewrite the source-level initialization into an
1671 // assignment statement. We use a block to collect multiple assignments.
1672 //
1673 // We mark the block as initializer block because we don't want the
1674 // rewriter to add a '.result' assignment to such a block (to get compliant
1675 // behavior for code such as print(eval('var x = 7')), and for cosmetic
1676 // reasons when pretty-printing. Also, unless an assignment (initialization)
1677 // is inside an initializer block, it is ignored.
1678 //
1679 // Create new block with one expected declaration.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001680 Block* block = new(zone()) Block(isolate(), NULL, 1, true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001681 int nvars = 0; // the number of variables declared
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001682 Handle<String> name;
Steve Blocka7e24c12009-10-30 11:49:00 +00001683 do {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001684 if (fni_ != NULL) fni_->Enter();
1685
Steve Blocka7e24c12009-10-30 11:49:00 +00001686 // Parse variable name.
1687 if (nvars > 0) Consume(Token::COMMA);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001688 name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001689 if (fni_ != NULL) fni_->PushVariableName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001690
Steve Block1e0659c2011-05-24 12:43:12 +01001691 // Strict mode variables may not be named eval or arguments
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001692 if (declaration_scope->is_strict_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01001693 ReportMessage("strict_var_name", Vector<const char*>::empty());
1694 *ok = false;
1695 return NULL;
1696 }
1697
Steve Blocka7e24c12009-10-30 11:49:00 +00001698 // Declare variable.
1699 // Note that we *always* must treat the initial value via a separate init
1700 // assignment for variables and constants because the value must be assigned
1701 // when the variable is encountered in the source. But the variable/constant
1702 // is declared (and set to 'undefined') upon entering the function within
1703 // which the variable or constant is declared. Only function variables have
1704 // an initial value in the declaration (because they are initialized upon
1705 // entering the function).
1706 //
1707 // If we have a const declaration, in an inner scope, the proxy is always
1708 // bound to the declared variable (independent of possibly surrounding with
1709 // statements).
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001710 Declare(name, mode, NULL, is_const /* always bound for CONST! */,
1711 CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00001712 nvars++;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001713 if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
Steve Block053d10c2011-06-13 19:13:29 +01001714 ReportMessageAt(scanner().location(), "too_many_variables",
1715 Vector<const char*>::empty());
1716 *ok = false;
1717 return NULL;
1718 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001719
1720 // Parse initialization expression if present and/or needed. A
1721 // declaration of the form:
1722 //
1723 // var v = x;
1724 //
1725 // is syntactic sugar for:
1726 //
1727 // var v; v = x;
1728 //
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001729 // In particular, we need to re-lookup 'v' (in top_scope_, not
1730 // declaration_scope) as it may be a different 'v' than the 'v' in the
1731 // declaration (e.g., if we are inside a 'with' statement or 'catch'
1732 // block).
Steve Blocka7e24c12009-10-30 11:49:00 +00001733 //
1734 // However, note that const declarations are different! A const
1735 // declaration of the form:
1736 //
1737 // const c = x;
1738 //
1739 // is *not* syntactic sugar for:
1740 //
1741 // const c; c = x;
1742 //
1743 // The "variable" c initialized to x is the same as the declared
1744 // one - there is no re-lookup (see the last parameter of the
1745 // Declare() call above).
1746
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001747 Scope* initialization_scope = is_const ? declaration_scope : top_scope_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001748 Expression* value = NULL;
1749 int position = -1;
1750 if (peek() == Token::ASSIGN) {
1751 Expect(Token::ASSIGN, CHECK_OK);
1752 position = scanner().location().beg_pos;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001753 value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001754 // Don't infer if it is "a = function(){...}();"-like expression.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001755 if (fni_ != NULL &&
1756 value->AsCall() == NULL &&
1757 value->AsCallNew() == NULL) {
1758 fni_->Infer();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001759 } else {
1760 fni_->RemoveLastFunction();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001761 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001762 }
1763
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001764 // Make sure that 'const x' and 'let x' initialize 'x' to undefined.
1765 if (value == NULL && needs_init) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001766 value = GetLiteralUndefined();
1767 }
1768
1769 // Global variable declarations must be compiled in a specific
1770 // way. When the script containing the global variable declaration
1771 // is entered, the global variable must be declared, so that if it
1772 // doesn't exist (not even in a prototype of the global object) it
1773 // gets created with an initial undefined value. This is handled
1774 // by the declarations part of the function representing the
1775 // top-level global code; see Runtime::DeclareGlobalVariable. If
1776 // it already exists (in the object or in a prototype), it is
1777 // *not* touched until the variable declaration statement is
1778 // executed.
1779 //
1780 // Executing the variable declaration statement will always
1781 // guarantee to give the global object a "local" variable; a
1782 // variable defined in the global object and not in any
1783 // prototype. This way, global variable declarations can shadow
1784 // properties in the prototype chain, but only after the variable
1785 // declaration statement has been executed. This is important in
1786 // browsers where the global object (window) has lots of
1787 // properties defined in prototype objects.
1788
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001789 if (initialization_scope->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001790 // Compute the arguments for the runtime call.
Ben Murdoch257744e2011-11-30 15:57:28 +00001791 ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001792 // We have at least 1 parameter.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001793 arguments->Add(NewLiteral(name));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001794 CallRuntime* initialize;
1795
1796 if (is_const) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001797 arguments->Add(value);
1798 value = NULL; // zap the value to avoid the unnecessary assignment
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001799
1800 // Construct the call to Runtime_InitializeConstGlobal
1801 // and add it to the initialization statement block.
1802 // Note that the function does different things depending on
1803 // the number of arguments (1 or 2).
Steve Blocka7e24c12009-10-30 11:49:00 +00001804 initialize =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001805 new(zone()) CallRuntime(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001806 isolate(),
1807 isolate()->factory()->InitializeConstGlobal_symbol(),
1808 Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
1809 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001810 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001811 // Add strict mode.
1812 // We may want to pass singleton to avoid Literal allocations.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001813 StrictModeFlag flag = initialization_scope->is_strict_mode()
1814 ? kStrictMode
1815 : kNonStrictMode;
1816 arguments->Add(NewNumberLiteral(flag));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001817
1818 // Be careful not to assign a value to the global variable if
1819 // we're in a with. The initialization value should not
1820 // necessarily be stored in the global object in that case,
1821 // which is why we need to generate a separate assignment node.
1822 if (value != NULL && !inside_with()) {
1823 arguments->Add(value);
1824 value = NULL; // zap the value to avoid the unnecessary assignment
1825 }
1826
1827 // Construct the call to Runtime_InitializeVarGlobal
1828 // and add it to the initialization statement block.
1829 // Note that the function does different things depending on
1830 // the number of arguments (2 or 3).
Steve Blocka7e24c12009-10-30 11:49:00 +00001831 initialize =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001832 new(zone()) CallRuntime(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001833 isolate(),
1834 isolate()->factory()->InitializeVarGlobal_symbol(),
1835 Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
1836 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001837 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001838
Ben Murdoch8b112d22011-06-08 16:22:53 +01001839 block->AddStatement(new(zone()) ExpressionStatement(initialize));
Steve Blocka7e24c12009-10-30 11:49:00 +00001840 }
1841
1842 // Add an assignment node to the initialization statement block if
1843 // we still have a pending initialization value. We must distinguish
1844 // between variables and constants: Variable initializations are simply
1845 // assignments (with all the consequences if they are inside a 'with'
1846 // statement - they may change a 'with' object property). Constant
1847 // initializations always assign to the declared constant which is
1848 // always at the function scope level. This is only relevant for
1849 // dynamically looked-up variables and constants (the start context
1850 // for constant lookups is always the function context, while it is
1851 // the top context for variables). Sigh...
1852 if (value != NULL) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001853 bool in_with = is_const ? false : inside_with();
1854 VariableProxy* proxy =
1855 initialization_scope->NewUnresolved(name, in_with);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001856 Assignment* assignment =
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001857 new(zone()) Assignment(isolate(), init_op, proxy, value, position);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001858 if (block) {
1859 block->AddStatement(new(zone()) ExpressionStatement(assignment));
1860 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001861 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001862
1863 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00001864 } while (peek() == Token::COMMA);
1865
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001866 // If there was a single non-const declaration, return it in the output
1867 // parameter for possible use by for/in.
1868 if (nvars == 1 && !is_const) {
1869 *out = name;
Steve Blocka7e24c12009-10-30 11:49:00 +00001870 }
1871
1872 return block;
1873}
1874
1875
1876static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
1877 ASSERT(!label.is_null());
1878 if (labels != NULL)
1879 for (int i = labels->length(); i-- > 0; )
1880 if (labels->at(i).is_identical_to(label))
1881 return true;
1882
1883 return false;
1884}
1885
1886
1887Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
1888 bool* ok) {
1889 // ExpressionStatement | LabelledStatement ::
1890 // Expression ';'
1891 // Identifier ':' Statement
Steve Block1e0659c2011-05-24 12:43:12 +01001892 bool starts_with_idenfifier = peek_any_identifier();
Steve Blocka7e24c12009-10-30 11:49:00 +00001893 Expression* expr = ParseExpression(true, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001894 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001895 expr->AsVariableProxy() != NULL &&
1896 !expr->AsVariableProxy()->is_this()) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001897 // Expression is a single identifier, and not, e.g., a parenthesized
1898 // identifier.
Steve Blocka7e24c12009-10-30 11:49:00 +00001899 VariableProxy* var = expr->AsVariableProxy();
1900 Handle<String> label = var->name();
1901 // TODO(1240780): We don't check for redeclaration of labels
1902 // during preparsing since keeping track of the set of active
1903 // labels requires nontrivial changes to the way scopes are
1904 // structured. However, these are probably changes we want to
1905 // make later anyway so we should go back and fix this then.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001906 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
1907 SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
1908 const char* elms[2] = { "Label", *c_string };
1909 Vector<const char*> args(elms, 2);
1910 ReportMessage("redeclaration", args);
1911 *ok = false;
1912 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001913 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001914 if (labels == NULL) labels = new(zone()) ZoneStringList(4);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001915 labels->Add(label);
1916 // Remove the "ghost" variable that turned out to be a label
1917 // from the top scope. This way, we don't try to resolve it
1918 // during the scope processing.
1919 top_scope_->RemoveUnresolved(var);
Steve Blocka7e24c12009-10-30 11:49:00 +00001920 Expect(Token::COLON, CHECK_OK);
1921 return ParseStatement(labels, ok);
1922 }
1923
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001924 // If we have an extension, we allow a native function declaration.
1925 // A native function declaration starts with "native function" with
1926 // no line-terminator between the two words.
1927 if (extension_ != NULL &&
1928 peek() == Token::FUNCTION &&
1929 !scanner().HasAnyLineTerminatorBeforeNext() &&
1930 expr != NULL &&
1931 expr->AsVariableProxy() != NULL &&
1932 expr->AsVariableProxy()->name()->Equals(
1933 isolate()->heap()->native_symbol()) &&
1934 !scanner().literal_contains_escapes()) {
1935 return ParseNativeDeclaration(ok);
1936 }
1937
Steve Blocka7e24c12009-10-30 11:49:00 +00001938 // Parsed expression statement.
1939 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001940 return new(zone()) ExpressionStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001941}
1942
1943
1944IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
1945 // IfStatement ::
1946 // 'if' '(' Expression ')' Statement ('else' Statement)?
1947
1948 Expect(Token::IF, CHECK_OK);
1949 Expect(Token::LPAREN, CHECK_OK);
1950 Expression* condition = ParseExpression(true, CHECK_OK);
1951 Expect(Token::RPAREN, CHECK_OK);
1952 Statement* then_statement = ParseStatement(labels, CHECK_OK);
1953 Statement* else_statement = NULL;
1954 if (peek() == Token::ELSE) {
1955 Next();
1956 else_statement = ParseStatement(labels, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001957 } else {
1958 else_statement = EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001959 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001960 return new(zone()) IfStatement(
1961 isolate(), condition, then_statement, else_statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00001962}
1963
1964
1965Statement* Parser::ParseContinueStatement(bool* ok) {
1966 // ContinueStatement ::
1967 // 'continue' Identifier? ';'
1968
1969 Expect(Token::CONTINUE, CHECK_OK);
1970 Handle<String> label = Handle<String>::null();
1971 Token::Value tok = peek();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001972 if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001973 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1974 label = ParseIdentifier(CHECK_OK);
1975 }
1976 IterationStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001977 target = LookupContinueTarget(label, CHECK_OK);
1978 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001979 // Illegal continue statement.
1980 const char* message = "illegal_continue";
1981 Vector<Handle<String> > args;
1982 if (!label.is_null()) {
1983 message = "unknown_label";
1984 args = Vector<Handle<String> >(&label, 1);
1985 }
1986 ReportMessageAt(scanner().location(), message, args);
1987 *ok = false;
1988 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001989 }
1990 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001991 return new(zone()) ContinueStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001992}
1993
1994
1995Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
1996 // BreakStatement ::
1997 // 'break' Identifier? ';'
1998
1999 Expect(Token::BREAK, CHECK_OK);
2000 Handle<String> label;
2001 Token::Value tok = peek();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002002 if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00002003 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2004 label = ParseIdentifier(CHECK_OK);
2005 }
2006 // Parse labeled break statements that target themselves into
2007 // empty statements, e.g. 'l1: l2: l3: break l2;'
2008 if (!label.is_null() && ContainsLabel(labels, label)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002009 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002010 }
2011 BreakableStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002012 target = LookupBreakTarget(label, CHECK_OK);
2013 if (target == NULL) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002014 // Illegal break statement.
2015 const char* message = "illegal_break";
2016 Vector<Handle<String> > args;
2017 if (!label.is_null()) {
2018 message = "unknown_label";
2019 args = Vector<Handle<String> >(&label, 1);
2020 }
2021 ReportMessageAt(scanner().location(), message, args);
2022 *ok = false;
2023 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00002024 }
2025 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002026 return new(zone()) BreakStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00002027}
2028
2029
2030Statement* Parser::ParseReturnStatement(bool* ok) {
2031 // ReturnStatement ::
2032 // 'return' Expression? ';'
2033
2034 // Consume the return token. It is necessary to do the before
2035 // reporting any errors on it, because of the way errors are
2036 // reported (underlining).
2037 Expect(Token::RETURN, CHECK_OK);
2038
2039 // An ECMAScript program is considered syntactically incorrect if it
2040 // contains a return statement that is not within the body of a
2041 // function. See ECMA-262, section 12.9, page 67.
2042 //
2043 // To be consistent with KJS we report the syntax error at runtime.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002044 Scope* declaration_scope = top_scope_->DeclarationScope();
2045 if (declaration_scope->is_global_scope() ||
2046 declaration_scope->is_eval_scope()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002047 Handle<String> type = isolate()->factory()->illegal_return_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002048 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
Ben Murdoch8b112d22011-06-08 16:22:53 +01002049 return new(zone()) ExpressionStatement(throw_error);
Steve Blocka7e24c12009-10-30 11:49:00 +00002050 }
2051
2052 Token::Value tok = peek();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002053 if (scanner().HasAnyLineTerminatorBeforeNext() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00002054 tok == Token::SEMICOLON ||
2055 tok == Token::RBRACE ||
2056 tok == Token::EOS) {
2057 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002058 return new(zone()) ReturnStatement(GetLiteralUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00002059 }
2060
2061 Expression* expr = ParseExpression(true, CHECK_OK);
2062 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002063 return new(zone()) ReturnStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00002064}
2065
2066
Steve Blocka7e24c12009-10-30 11:49:00 +00002067Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
2068 // WithStatement ::
2069 // 'with' '(' Expression ')' Statement
2070
2071 Expect(Token::WITH, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002072
Steve Block44f0eee2011-05-26 01:26:41 +01002073 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002074 ReportMessage("strict_mode_with", Vector<const char*>::empty());
2075 *ok = false;
2076 return NULL;
2077 }
2078
Steve Blocka7e24c12009-10-30 11:49:00 +00002079 Expect(Token::LPAREN, CHECK_OK);
2080 Expression* expr = ParseExpression(true, CHECK_OK);
2081 Expect(Token::RPAREN, CHECK_OK);
2082
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002083 ++with_nesting_level_;
2084 top_scope_->DeclarationScope()->RecordWithStatement();
2085 Statement* stmt = ParseStatement(labels, CHECK_OK);
2086 --with_nesting_level_;
2087 return new(zone()) WithStatement(expr, stmt);
Steve Blocka7e24c12009-10-30 11:49:00 +00002088}
2089
2090
2091CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
2092 // CaseClause ::
2093 // 'case' Expression ':' Statement*
2094 // 'default' ':' Statement*
2095
2096 Expression* label = NULL; // NULL expression indicates default case
2097 if (peek() == Token::CASE) {
2098 Expect(Token::CASE, CHECK_OK);
2099 label = ParseExpression(true, CHECK_OK);
2100 } else {
2101 Expect(Token::DEFAULT, CHECK_OK);
2102 if (*default_seen_ptr) {
2103 ReportMessage("multiple_defaults_in_switch",
2104 Vector<const char*>::empty());
2105 *ok = false;
2106 return NULL;
2107 }
2108 *default_seen_ptr = true;
2109 }
2110 Expect(Token::COLON, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002111 int pos = scanner().location().beg_pos;
Ben Murdoch257744e2011-11-30 15:57:28 +00002112 ZoneList<Statement*>* statements = new(zone()) ZoneList<Statement*>(5);
Steve Blocka7e24c12009-10-30 11:49:00 +00002113 while (peek() != Token::CASE &&
2114 peek() != Token::DEFAULT &&
2115 peek() != Token::RBRACE) {
2116 Statement* stat = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002117 statements->Add(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00002118 }
2119
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002120 return new(zone()) CaseClause(isolate(), label, statements, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002121}
2122
2123
2124SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
2125 bool* ok) {
2126 // SwitchStatement ::
2127 // 'switch' '(' Expression ')' '{' CaseClause* '}'
2128
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002129 SwitchStatement* statement = new(zone()) SwitchStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002130 Target target(&this->target_stack_, statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00002131
2132 Expect(Token::SWITCH, CHECK_OK);
2133 Expect(Token::LPAREN, CHECK_OK);
2134 Expression* tag = ParseExpression(true, CHECK_OK);
2135 Expect(Token::RPAREN, CHECK_OK);
2136
2137 bool default_seen = false;
Ben Murdoch257744e2011-11-30 15:57:28 +00002138 ZoneList<CaseClause*>* cases = new(zone()) ZoneList<CaseClause*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002139 Expect(Token::LBRACE, CHECK_OK);
2140 while (peek() != Token::RBRACE) {
2141 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002142 cases->Add(clause);
Steve Blocka7e24c12009-10-30 11:49:00 +00002143 }
2144 Expect(Token::RBRACE, CHECK_OK);
2145
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002146 if (statement) statement->Initialize(tag, cases);
Steve Blocka7e24c12009-10-30 11:49:00 +00002147 return statement;
2148}
2149
2150
2151Statement* Parser::ParseThrowStatement(bool* ok) {
2152 // ThrowStatement ::
2153 // 'throw' Expression ';'
2154
2155 Expect(Token::THROW, CHECK_OK);
2156 int pos = scanner().location().beg_pos;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002157 if (scanner().HasAnyLineTerminatorBeforeNext()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002158 ReportMessage("newline_after_throw", Vector<const char*>::empty());
2159 *ok = false;
2160 return NULL;
2161 }
2162 Expression* exception = ParseExpression(true, CHECK_OK);
2163 ExpectSemicolon(CHECK_OK);
2164
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002165 return new(zone()) ExpressionStatement(
2166 new(zone()) Throw(isolate(), exception, pos));
Steve Blocka7e24c12009-10-30 11:49:00 +00002167}
2168
2169
2170TryStatement* Parser::ParseTryStatement(bool* ok) {
2171 // TryStatement ::
2172 // 'try' Block Catch
2173 // 'try' Block Finally
2174 // 'try' Block Catch Finally
2175 //
2176 // Catch ::
2177 // 'catch' '(' Identifier ')' Block
2178 //
2179 // Finally ::
2180 // 'finally' Block
2181
2182 Expect(Token::TRY, CHECK_OK);
2183
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002184 TargetCollector try_collector;
Steve Blocka7e24c12009-10-30 11:49:00 +00002185 Block* try_block;
2186
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002187 { Target target(&this->target_stack_, &try_collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00002188 try_block = ParseBlock(NULL, CHECK_OK);
2189 }
2190
Steve Blocka7e24c12009-10-30 11:49:00 +00002191 Token::Value tok = peek();
2192 if (tok != Token::CATCH && tok != Token::FINALLY) {
2193 ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
2194 *ok = false;
2195 return NULL;
2196 }
2197
2198 // If we can break out from the catch block and there is a finally block,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002199 // then we will need to collect escaping targets from the catch
2200 // block. Since we don't know yet if there will be a finally block, we
2201 // always collect the targets.
2202 TargetCollector catch_collector;
2203 Scope* catch_scope = NULL;
2204 Variable* catch_variable = NULL;
2205 Block* catch_block = NULL;
2206 Handle<String> name;
Steve Blocka7e24c12009-10-30 11:49:00 +00002207 if (tok == Token::CATCH) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002208 Consume(Token::CATCH);
2209
2210 Expect(Token::LPAREN, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002211 name = ParseIdentifier(CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002212
Steve Block44f0eee2011-05-26 01:26:41 +01002213 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01002214 ReportMessage("strict_catch_variable", Vector<const char*>::empty());
2215 *ok = false;
2216 return NULL;
2217 }
2218
Steve Blocka7e24c12009-10-30 11:49:00 +00002219 Expect(Token::RPAREN, CHECK_OK);
2220
2221 if (peek() == Token::LBRACE) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002222 // Rewrite the catch body { B } to a block:
2223 // { { B } ExitContext; }.
2224 Target target(&this->target_stack_, &catch_collector);
2225 catch_scope = NewScope(top_scope_, Scope::CATCH_SCOPE, inside_with());
2226 if (top_scope_->is_strict_mode()) {
2227 catch_scope->EnableStrictMode();
Steve Blocka7e24c12009-10-30 11:49:00 +00002228 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002229 catch_variable = catch_scope->DeclareLocal(name, Variable::VAR);
2230 catch_block = new(zone()) Block(isolate(), NULL, 2, false);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002231
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002232 Scope* saved_scope = top_scope_;
2233 top_scope_ = catch_scope;
2234 Block* catch_body = ParseBlock(NULL, CHECK_OK);
2235 top_scope_ = saved_scope;
2236 catch_block->AddStatement(catch_body);
2237 catch_block->AddStatement(new(zone()) ExitContextStatement());
Steve Blocka7e24c12009-10-30 11:49:00 +00002238 } else {
2239 Expect(Token::LBRACE, CHECK_OK);
2240 }
2241
2242 tok = peek();
2243 }
2244
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002245 Block* finally_block = NULL;
2246 if (tok == Token::FINALLY || catch_block == NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002247 Consume(Token::FINALLY);
Steve Blocka7e24c12009-10-30 11:49:00 +00002248 finally_block = ParseBlock(NULL, CHECK_OK);
2249 }
2250
2251 // Simplify the AST nodes by converting:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002252 // 'try B0 catch B1 finally B2'
Steve Blocka7e24c12009-10-30 11:49:00 +00002253 // to:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002254 // 'try { try B0 catch B1 } finally B2'
Steve Blocka7e24c12009-10-30 11:49:00 +00002255
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002256 if (catch_block != NULL && finally_block != NULL) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002257 // If we have both, create an inner try/catch.
2258 ASSERT(catch_scope != NULL && catch_variable != NULL);
Steve Block3ce2e202009-11-05 08:53:23 +00002259 TryCatchStatement* statement =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002260 new(zone()) TryCatchStatement(try_block,
2261 catch_scope,
2262 catch_variable,
2263 catch_block);
2264 statement->set_escaping_targets(try_collector.targets());
2265 try_block = new(zone()) Block(isolate(), NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00002266 try_block->AddStatement(statement);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002267 catch_block = NULL; // Clear to indicate it's been handled.
Steve Blocka7e24c12009-10-30 11:49:00 +00002268 }
2269
2270 TryStatement* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002271 if (catch_block != NULL) {
2272 ASSERT(finally_block == NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002273 ASSERT(catch_scope != NULL && catch_variable != NULL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002274 result =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002275 new(zone()) TryCatchStatement(try_block,
2276 catch_scope,
2277 catch_variable,
2278 catch_block);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002279 } else {
2280 ASSERT(finally_block != NULL);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002281 result = new(zone()) TryFinallyStatement(try_block, finally_block);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002282 // Combine the jump targets of the try block and the possible catch block.
2283 try_collector.targets()->AddAll(*catch_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002284 }
2285
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002286 result->set_escaping_targets(try_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002287 return result;
2288}
2289
2290
Steve Block3ce2e202009-11-05 08:53:23 +00002291DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
2292 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002293 // DoStatement ::
2294 // 'do' Statement 'while' '(' Expression ')' ';'
2295
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002296 DoWhileStatement* loop = new(zone()) DoWhileStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002297 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002298
2299 Expect(Token::DO, CHECK_OK);
2300 Statement* body = ParseStatement(NULL, CHECK_OK);
2301 Expect(Token::WHILE, CHECK_OK);
2302 Expect(Token::LPAREN, CHECK_OK);
Steve Blockd0582a62009-12-15 09:54:21 +00002303
2304 if (loop != NULL) {
2305 int position = scanner().location().beg_pos;
2306 loop->set_condition_position(position);
2307 }
2308
Steve Blocka7e24c12009-10-30 11:49:00 +00002309 Expression* cond = ParseExpression(true, CHECK_OK);
2310 Expect(Token::RPAREN, CHECK_OK);
2311
2312 // Allow do-statements to be terminated with and without
2313 // semi-colons. This allows code such as 'do;while(0)return' to
2314 // parse, which would not be the case if we had used the
2315 // ExpectSemicolon() functionality here.
2316 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2317
Steve Block3ce2e202009-11-05 08:53:23 +00002318 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002319 return loop;
2320}
2321
2322
Steve Block3ce2e202009-11-05 08:53:23 +00002323WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002324 // WhileStatement ::
2325 // 'while' '(' Expression ')' Statement
2326
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002327 WhileStatement* loop = new(zone()) WhileStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002328 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002329
2330 Expect(Token::WHILE, CHECK_OK);
2331 Expect(Token::LPAREN, CHECK_OK);
2332 Expression* cond = ParseExpression(true, CHECK_OK);
2333 Expect(Token::RPAREN, CHECK_OK);
2334 Statement* body = ParseStatement(NULL, CHECK_OK);
2335
Steve Block3ce2e202009-11-05 08:53:23 +00002336 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002337 return loop;
2338}
2339
2340
2341Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
2342 // ForStatement ::
2343 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
2344
2345 Statement* init = NULL;
2346
2347 Expect(Token::FOR, CHECK_OK);
2348 Expect(Token::LPAREN, CHECK_OK);
2349 if (peek() != Token::SEMICOLON) {
2350 if (peek() == Token::VAR || peek() == Token::CONST) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002351 Handle<String> name;
Steve Blocka7e24c12009-10-30 11:49:00 +00002352 Block* variable_statement =
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002353 ParseVariableDeclarations(kForStatement, &name, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002354
2355 if (peek() == Token::IN && !name.is_null()) {
2356 VariableProxy* each = top_scope_->NewUnresolved(name, inside_with());
2357 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002358 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002359
2360 Expect(Token::IN, CHECK_OK);
2361 Expression* enumerable = ParseExpression(true, CHECK_OK);
2362 Expect(Token::RPAREN, CHECK_OK);
2363
2364 Statement* body = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002365 loop->Initialize(each, enumerable, body);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002366 Block* result = new(zone()) Block(isolate(), NULL, 2, false);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002367 result->AddStatement(variable_statement);
2368 result->AddStatement(loop);
2369 // Parsed for-in loop w/ variable/const declaration.
2370 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00002371 } else {
2372 init = variable_statement;
2373 }
2374
2375 } else {
2376 Expression* expression = ParseExpression(false, CHECK_OK);
2377 if (peek() == Token::IN) {
2378 // Signal a reference error if the expression is an invalid
2379 // left-hand side expression. We could report this as a syntax
2380 // error here but for compatibility with JSC we choose to report
2381 // the error at runtime.
2382 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002383 Handle<String> type =
2384 isolate()->factory()->invalid_lhs_in_for_in_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002385 expression = NewThrowReferenceError(type);
2386 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002387 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002388 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002389
2390 Expect(Token::IN, CHECK_OK);
2391 Expression* enumerable = ParseExpression(true, CHECK_OK);
2392 Expect(Token::RPAREN, CHECK_OK);
2393
2394 Statement* body = ParseStatement(NULL, CHECK_OK);
2395 if (loop) loop->Initialize(expression, enumerable, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002396 // Parsed for-in loop.
2397 return loop;
2398
2399 } else {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002400 init = new(zone()) ExpressionStatement(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002401 }
2402 }
2403 }
2404
2405 // Standard 'for' loop
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002406 ForStatement* loop = new(zone()) ForStatement(isolate(), labels);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002407 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002408
2409 // Parsed initializer at this point.
2410 Expect(Token::SEMICOLON, CHECK_OK);
2411
2412 Expression* cond = NULL;
2413 if (peek() != Token::SEMICOLON) {
2414 cond = ParseExpression(true, CHECK_OK);
2415 }
2416 Expect(Token::SEMICOLON, CHECK_OK);
2417
2418 Statement* next = NULL;
2419 if (peek() != Token::RPAREN) {
2420 Expression* exp = ParseExpression(true, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002421 next = new(zone()) ExpressionStatement(exp);
Steve Blocka7e24c12009-10-30 11:49:00 +00002422 }
2423 Expect(Token::RPAREN, CHECK_OK);
2424
2425 Statement* body = ParseStatement(NULL, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002426 if (loop) loop->Initialize(init, cond, next, body);
2427 return loop;
2428}
2429
2430
2431// Precedence = 1
2432Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
2433 // Expression ::
2434 // AssignmentExpression
2435 // Expression ',' AssignmentExpression
2436
2437 Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
2438 while (peek() == Token::COMMA) {
2439 Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002440 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002441 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002442 result = new(zone()) BinaryOperation(
2443 isolate(), Token::COMMA, result, right, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002444 }
2445 return result;
2446}
2447
2448
2449// Precedence = 2
2450Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
2451 // AssignmentExpression ::
2452 // ConditionalExpression
2453 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2454
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002455 if (fni_ != NULL) fni_->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00002456 Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
2457
2458 if (!Token::IsAssignmentOp(peek())) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002459 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00002460 // Parsed conditional expression only (no assignment).
2461 return expression;
2462 }
2463
2464 // Signal a reference error if the expression is an invalid left-hand
2465 // side expression. We could report this as a syntax error here but
2466 // for compatibility with JSC we choose to report the error at
2467 // runtime.
2468 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002469 Handle<String> type =
2470 isolate()->factory()->invalid_lhs_in_assignment_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002471 expression = NewThrowReferenceError(type);
2472 }
2473
Steve Block44f0eee2011-05-26 01:26:41 +01002474 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002475 // Assignment to eval or arguments is disallowed in strict mode.
2476 CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
2477 }
2478
Steve Blocka7e24c12009-10-30 11:49:00 +00002479 Token::Value op = Next(); // Get assignment operator.
2480 int pos = scanner().location().beg_pos;
2481 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2482
2483 // TODO(1231235): We try to estimate the set of properties set by
2484 // constructors. We define a new property whenever there is an
2485 // assignment to a property of 'this'. We should probably only add
2486 // properties if we haven't seen them before. Otherwise we'll
2487 // probably overestimate the number of properties.
2488 Property* property = expression ? expression->AsProperty() : NULL;
2489 if (op == Token::ASSIGN &&
2490 property != NULL &&
2491 property->obj()->AsVariableProxy() != NULL &&
2492 property->obj()->AsVariableProxy()->is_this()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002493 lexical_scope_->AddProperty();
Steve Blocka7e24c12009-10-30 11:49:00 +00002494 }
2495
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002496 // If we assign a function literal to a property we pretenure the
2497 // literal so it can be added as a constant function property.
2498 if (property != NULL && right->AsFunctionLiteral() != NULL) {
2499 right->AsFunctionLiteral()->set_pretenure(true);
2500 }
2501
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002502 if (fni_ != NULL) {
2503 // Check if the right hand side is a call to avoid inferring a
2504 // name if we're dealing with "a = function(){...}();"-like
2505 // expression.
2506 if ((op == Token::INIT_VAR
2507 || op == Token::INIT_CONST
2508 || op == Token::ASSIGN)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002509 && (right->AsCall() == NULL && right->AsCallNew() == NULL)) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002510 fni_->Infer();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002511 } else {
2512 fni_->RemoveLastFunction();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002513 }
2514 fni_->Leave();
2515 }
2516
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002517 return new(zone()) Assignment(isolate(), op, expression, right, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002518}
2519
2520
2521// Precedence = 3
2522Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
2523 // ConditionalExpression ::
2524 // LogicalOrExpression
2525 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
2526
2527 // We start using the binary expression parser for prec >= 4 only!
2528 Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
2529 if (peek() != Token::CONDITIONAL) return expression;
2530 Consume(Token::CONDITIONAL);
2531 // In parsing the first assignment expression in conditional
2532 // expressions we always accept the 'in' keyword; see ECMA-262,
2533 // section 11.12, page 58.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002534 int left_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002535 Expression* left = ParseAssignmentExpression(true, CHECK_OK);
2536 Expect(Token::COLON, CHECK_OK);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002537 int right_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002538 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002539 return new(zone()) Conditional(
2540 isolate(), expression, left, right, left_position, right_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002541}
2542
2543
2544static int Precedence(Token::Value tok, bool accept_IN) {
2545 if (tok == Token::IN && !accept_IN)
2546 return 0; // 0 precedence will terminate binary expression parsing
2547
2548 return Token::Precedence(tok);
2549}
2550
2551
2552// Precedence >= 4
2553Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
2554 ASSERT(prec >= 4);
2555 Expression* x = ParseUnaryExpression(CHECK_OK);
2556 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
2557 // prec1 >= 4
2558 while (Precedence(peek(), accept_IN) == prec1) {
2559 Token::Value op = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002560 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002561 Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
2562
2563 // Compute some expressions involving only number literals.
2564 if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
2565 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
2566 double x_val = x->AsLiteral()->handle()->Number();
2567 double y_val = y->AsLiteral()->handle()->Number();
2568
2569 switch (op) {
2570 case Token::ADD:
2571 x = NewNumberLiteral(x_val + y_val);
2572 continue;
2573 case Token::SUB:
2574 x = NewNumberLiteral(x_val - y_val);
2575 continue;
2576 case Token::MUL:
2577 x = NewNumberLiteral(x_val * y_val);
2578 continue;
2579 case Token::DIV:
2580 x = NewNumberLiteral(x_val / y_val);
2581 continue;
2582 case Token::BIT_OR:
2583 x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
2584 continue;
2585 case Token::BIT_AND:
2586 x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
2587 continue;
2588 case Token::BIT_XOR:
2589 x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
2590 continue;
2591 case Token::SHL: {
2592 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
2593 x = NewNumberLiteral(value);
2594 continue;
2595 }
2596 case Token::SHR: {
2597 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2598 uint32_t value = DoubleToUint32(x_val) >> shift;
2599 x = NewNumberLiteral(value);
2600 continue;
2601 }
2602 case Token::SAR: {
2603 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2604 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
2605 x = NewNumberLiteral(value);
2606 continue;
2607 }
2608 default:
2609 break;
2610 }
2611 }
2612
Steve Blocka7e24c12009-10-30 11:49:00 +00002613 // For now we distinguish between comparisons and other binary
2614 // operations. (We could combine the two and get rid of this
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002615 // code and AST node eventually.)
Steve Blocka7e24c12009-10-30 11:49:00 +00002616 if (Token::IsCompareOp(op)) {
2617 // We have a comparison.
2618 Token::Value cmp = op;
2619 switch (op) {
2620 case Token::NE: cmp = Token::EQ; break;
2621 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
2622 default: break;
2623 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002624 x = NewCompareNode(cmp, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002625 if (cmp != op) {
2626 // The comparison was negated - add a NOT.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002627 x = new(zone()) UnaryOperation(isolate(), Token::NOT, x, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002628 }
2629
2630 } else {
2631 // We have a "normal" binary operation.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002632 x = new(zone()) BinaryOperation(isolate(), op, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002633 }
2634 }
2635 }
2636 return x;
2637}
2638
2639
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002640Expression* Parser::NewCompareNode(Token::Value op,
2641 Expression* x,
2642 Expression* y,
2643 int position) {
2644 ASSERT(op != Token::NE && op != Token::NE_STRICT);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002645 if (op == Token::EQ || op == Token::EQ_STRICT) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002646 bool is_strict = (op == Token::EQ_STRICT);
2647 Literal* x_literal = x->AsLiteral();
2648 if (x_literal != NULL && x_literal->IsNull()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002649 return new(zone()) CompareToNull(isolate(), is_strict, y);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002650 }
2651
2652 Literal* y_literal = y->AsLiteral();
2653 if (y_literal != NULL && y_literal->IsNull()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002654 return new(zone()) CompareToNull(isolate(), is_strict, x);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002655 }
2656 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002657 return new(zone()) CompareOperation(isolate(), op, x, y, position);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002658}
2659
2660
Steve Blocka7e24c12009-10-30 11:49:00 +00002661Expression* Parser::ParseUnaryExpression(bool* ok) {
2662 // UnaryExpression ::
2663 // PostfixExpression
2664 // 'delete' UnaryExpression
2665 // 'void' UnaryExpression
2666 // 'typeof' UnaryExpression
2667 // '++' UnaryExpression
2668 // '--' UnaryExpression
2669 // '+' UnaryExpression
2670 // '-' UnaryExpression
2671 // '~' UnaryExpression
2672 // '!' UnaryExpression
2673
2674 Token::Value op = peek();
2675 if (Token::IsUnaryOp(op)) {
2676 op = Next();
Ben Murdoch257744e2011-11-30 15:57:28 +00002677 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002678 Expression* expression = ParseUnaryExpression(CHECK_OK);
2679
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002680 if (expression != NULL && (expression->AsLiteral() != NULL)) {
2681 Handle<Object> literal = expression->AsLiteral()->handle();
2682 if (op == Token::NOT) {
2683 // Convert the literal to a boolean condition and negate it.
2684 bool condition = literal->ToBoolean()->IsTrue();
2685 Handle<Object> result(isolate()->heap()->ToBoolean(!condition));
2686 return NewLiteral(result);
2687 } else if (literal->IsNumber()) {
2688 // Compute some expressions involving only number literals.
2689 double value = literal->Number();
2690 switch (op) {
2691 case Token::ADD:
2692 return expression;
2693 case Token::SUB:
2694 return NewNumberLiteral(-value);
2695 case Token::BIT_NOT:
2696 return NewNumberLiteral(~DoubleToInt32(value));
2697 default:
2698 break;
2699 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002700 }
2701 }
2702
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002703 // "delete identifier" is a syntax error in strict mode.
Steve Block44f0eee2011-05-26 01:26:41 +01002704 if (op == Token::DELETE && top_scope_->is_strict_mode()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002705 VariableProxy* operand = expression->AsVariableProxy();
2706 if (operand != NULL && !operand->is_this()) {
2707 ReportMessage("strict_delete", Vector<const char*>::empty());
2708 *ok = false;
2709 return NULL;
2710 }
2711 }
2712
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002713 return new(zone()) UnaryOperation(isolate(), op, expression, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002714
2715 } else if (Token::IsCountOp(op)) {
2716 op = Next();
2717 Expression* expression = ParseUnaryExpression(CHECK_OK);
2718 // Signal a reference error if the expression is an invalid
2719 // left-hand side expression. We could report this as a syntax
2720 // error here but for compatibility with JSC we choose to report the
2721 // error at runtime.
2722 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002723 Handle<String> type =
2724 isolate()->factory()->invalid_lhs_in_prefix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002725 expression = NewThrowReferenceError(type);
2726 }
Steve Block1e0659c2011-05-24 12:43:12 +01002727
Steve Block44f0eee2011-05-26 01:26:41 +01002728 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002729 // Prefix expression operand in strict mode may not be eval or arguments.
2730 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2731 }
2732
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002733 int position = scanner().location().beg_pos;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002734 return new(zone()) CountOperation(isolate(),
2735 op,
Ben Murdoch8b112d22011-06-08 16:22:53 +01002736 true /* prefix */,
2737 expression,
2738 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002739
2740 } else {
2741 return ParsePostfixExpression(ok);
2742 }
2743}
2744
2745
2746Expression* Parser::ParsePostfixExpression(bool* ok) {
2747 // PostfixExpression ::
2748 // LeftHandSideExpression ('++' | '--')?
2749
2750 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002751 if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Ben Murdochb0fe1622011-05-05 13:52:32 +01002752 Token::IsCountOp(peek())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002753 // Signal a reference error if the expression is an invalid
2754 // left-hand side expression. We could report this as a syntax
2755 // error here but for compatibility with JSC we choose to report the
2756 // error at runtime.
2757 if (expression == NULL || !expression->IsValidLeftHandSide()) {
Steve Block44f0eee2011-05-26 01:26:41 +01002758 Handle<String> type =
2759 isolate()->factory()->invalid_lhs_in_postfix_op_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00002760 expression = NewThrowReferenceError(type);
2761 }
Steve Block1e0659c2011-05-24 12:43:12 +01002762
Steve Block44f0eee2011-05-26 01:26:41 +01002763 if (top_scope_->is_strict_mode()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002764 // Postfix expression operand in strict mode may not be eval or arguments.
2765 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2766 }
2767
Steve Blocka7e24c12009-10-30 11:49:00 +00002768 Token::Value next = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002769 int position = scanner().location().beg_pos;
Ben Murdoch8b112d22011-06-08 16:22:53 +01002770 expression =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002771 new(zone()) CountOperation(isolate(),
2772 next,
Ben Murdoch8b112d22011-06-08 16:22:53 +01002773 false /* postfix */,
2774 expression,
2775 position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002776 }
2777 return expression;
2778}
2779
2780
2781Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
2782 // LeftHandSideExpression ::
2783 // (NewExpression | MemberExpression) ...
2784
2785 Expression* result;
2786 if (peek() == Token::NEW) {
2787 result = ParseNewExpression(CHECK_OK);
2788 } else {
2789 result = ParseMemberExpression(CHECK_OK);
2790 }
2791
2792 while (true) {
2793 switch (peek()) {
2794 case Token::LBRACK: {
2795 Consume(Token::LBRACK);
2796 int pos = scanner().location().beg_pos;
2797 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002798 result = new(zone()) Property(isolate(), result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002799 Expect(Token::RBRACK, CHECK_OK);
2800 break;
2801 }
2802
2803 case Token::LPAREN: {
2804 int pos = scanner().location().beg_pos;
2805 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2806
2807 // Keep track of eval() calls since they disable all local variable
2808 // optimizations.
2809 // The calls that need special treatment are the
2810 // direct (i.e. not aliased) eval calls. These calls are all of the
2811 // form eval(...) with no explicit receiver object where eval is not
Ben Murdochb8e0da22011-05-16 14:20:40 +01002812 // declared in the current scope chain.
2813 // These calls are marked as potentially direct eval calls. Whether
2814 // they are actually direct calls to eval is determined at run time.
2815 // TODO(994): In ES5, it doesn't matter if the "eval" var is declared
2816 // in the local scope chain. It only matters that it's called "eval",
2817 // is called without a receiver and it refers to the original eval
2818 // function.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002819 VariableProxy* callee = result->AsVariableProxy();
Steve Block44f0eee2011-05-26 01:26:41 +01002820 if (callee != NULL &&
2821 callee->IsVariable(isolate()->factory()->eval_symbol())) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002822 Handle<String> name = callee->name();
2823 Variable* var = top_scope_->Lookup(name);
2824 if (var == NULL) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002825 top_scope_->DeclarationScope()->RecordEvalCall();
Steve Blocka7e24c12009-10-30 11:49:00 +00002826 }
2827 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002828 result = NewCall(result, args, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002829 break;
2830 }
2831
2832 case Token::PERIOD: {
2833 Consume(Token::PERIOD);
2834 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002835 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002836 result = new(zone()) Property(isolate(),
2837 result,
2838 NewLiteral(name),
2839 pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002840 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002841 break;
2842 }
2843
2844 default:
2845 return result;
2846 }
2847 }
2848}
2849
2850
Steve Blocka7e24c12009-10-30 11:49:00 +00002851Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
2852 // NewExpression ::
2853 // ('new')+ MemberExpression
2854
2855 // The grammar for new expressions is pretty warped. The keyword
2856 // 'new' can either be a part of the new expression (where it isn't
2857 // followed by an argument list) or a part of the member expression,
2858 // where it must be followed by an argument list. To accommodate
2859 // this, we parse the 'new' keywords greedily and keep track of how
2860 // many we have parsed. This information is then passed on to the
2861 // member expression parser, which is only allowed to match argument
2862 // lists as long as it has 'new' prefixes left
2863 Expect(Token::NEW, CHECK_OK);
2864 PositionStack::Element pos(stack, scanner().location().beg_pos);
2865
2866 Expression* result;
2867 if (peek() == Token::NEW) {
2868 result = ParseNewPrefix(stack, CHECK_OK);
2869 } else {
2870 result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
2871 }
2872
2873 if (!stack->is_empty()) {
2874 int last = stack->pop();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002875 result = new(zone()) CallNew(isolate(),
2876 result,
Ben Murdoch257744e2011-11-30 15:57:28 +00002877 new(zone()) ZoneList<Expression*>(0),
2878 last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002879 }
2880 return result;
2881}
2882
2883
2884Expression* Parser::ParseNewExpression(bool* ok) {
2885 PositionStack stack(ok);
2886 return ParseNewPrefix(&stack, ok);
2887}
2888
2889
2890Expression* Parser::ParseMemberExpression(bool* ok) {
2891 return ParseMemberWithNewPrefixesExpression(NULL, ok);
2892}
2893
2894
2895Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
2896 bool* ok) {
2897 // MemberExpression ::
2898 // (PrimaryExpression | FunctionLiteral)
2899 // ('[' Expression ']' | '.' Identifier | Arguments)*
2900
2901 // Parse the initial primary or function expression.
2902 Expression* result = NULL;
2903 if (peek() == Token::FUNCTION) {
2904 Expect(Token::FUNCTION, CHECK_OK);
2905 int function_token_position = scanner().location().beg_pos;
2906 Handle<String> name;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002907 bool is_strict_reserved_name = false;
Steve Block1e0659c2011-05-24 12:43:12 +01002908 if (peek_any_identifier()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002909 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
2910 CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01002911 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002912 FunctionLiteral::Type type = name.is_null()
2913 ? FunctionLiteral::ANONYMOUS_EXPRESSION
2914 : FunctionLiteral::NAMED_EXPRESSION;
2915 result = ParseFunctionLiteral(name,
2916 is_strict_reserved_name,
2917 function_token_position,
2918 type,
2919 CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002920 } else {
2921 result = ParsePrimaryExpression(CHECK_OK);
2922 }
2923
2924 while (true) {
2925 switch (peek()) {
2926 case Token::LBRACK: {
2927 Consume(Token::LBRACK);
2928 int pos = scanner().location().beg_pos;
2929 Expression* index = ParseExpression(true, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002930 result = new(zone()) Property(isolate(), result, index, pos);
2931 if (fni_ != NULL) {
2932 if (index->IsPropertyName()) {
2933 fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
2934 } else {
2935 fni_->PushLiteralName(
2936 isolate()->factory()->anonymous_function_symbol());
2937 }
2938 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002939 Expect(Token::RBRACK, CHECK_OK);
2940 break;
2941 }
2942 case Token::PERIOD: {
2943 Consume(Token::PERIOD);
2944 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002945 Handle<String> name = ParseIdentifierName(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002946 result = new(zone()) Property(isolate(),
2947 result,
2948 NewLiteral(name),
2949 pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002950 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002951 break;
2952 }
2953 case Token::LPAREN: {
2954 if ((stack == NULL) || stack->is_empty()) return result;
2955 // Consume one of the new prefixes (already parsed).
2956 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2957 int last = stack->pop();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002958 result = new(zone()) CallNew(isolate(), result, args, last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002959 break;
2960 }
2961 default:
2962 return result;
2963 }
2964 }
2965}
2966
2967
2968DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
2969 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
2970 // contexts this is used as a statement which invokes the debugger as i a
2971 // break point is present.
2972 // DebuggerStatement ::
2973 // 'debugger' ';'
2974
2975 Expect(Token::DEBUGGER, CHECK_OK);
2976 ExpectSemicolon(CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01002977 return new(zone()) DebuggerStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002978}
2979
2980
2981void Parser::ReportUnexpectedToken(Token::Value token) {
2982 // We don't report stack overflows here, to avoid increasing the
2983 // stack depth even further. Instead we report it after parsing is
Leon Clarke4515c472010-02-03 11:58:03 +00002984 // over, in ParseProgram/ParseJson.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002985 if (token == Token::ILLEGAL && stack_overflow_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002986 // Four of the tokens are treated specially
2987 switch (token) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002988 case Token::EOS:
2989 return ReportMessage("unexpected_eos", Vector<const char*>::empty());
2990 case Token::NUMBER:
2991 return ReportMessage("unexpected_token_number",
2992 Vector<const char*>::empty());
2993 case Token::STRING:
2994 return ReportMessage("unexpected_token_string",
2995 Vector<const char*>::empty());
2996 case Token::IDENTIFIER:
2997 return ReportMessage("unexpected_token_identifier",
2998 Vector<const char*>::empty());
Steve Block1e0659c2011-05-24 12:43:12 +01002999 case Token::FUTURE_RESERVED_WORD:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003000 return ReportMessage("unexpected_reserved",
3001 Vector<const char*>::empty());
3002 case Token::FUTURE_STRICT_RESERVED_WORD:
Steve Block44f0eee2011-05-26 01:26:41 +01003003 return ReportMessage(top_scope_->is_strict_mode() ?
Steve Block1e0659c2011-05-24 12:43:12 +01003004 "unexpected_strict_reserved" :
3005 "unexpected_token_identifier",
3006 Vector<const char*>::empty());
Ben Murdochb0fe1622011-05-05 13:52:32 +01003007 default:
3008 const char* name = Token::String(token);
3009 ASSERT(name != NULL);
3010 ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00003011 }
3012}
3013
3014
Leon Clarkeac952652010-07-15 11:15:24 +01003015void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
3016 SmartPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
3017 const char* element[1] = { *name_string };
3018 ReportMessage("invalid_preparser_data",
3019 Vector<const char*>(element, 1));
3020 *ok = false;
3021}
3022
3023
Steve Blocka7e24c12009-10-30 11:49:00 +00003024Expression* Parser::ParsePrimaryExpression(bool* ok) {
3025 // PrimaryExpression ::
3026 // 'this'
3027 // 'null'
3028 // 'true'
3029 // 'false'
3030 // Identifier
3031 // Number
3032 // String
3033 // ArrayLiteral
3034 // ObjectLiteral
3035 // RegExpLiteral
3036 // '(' Expression ')'
3037
3038 Expression* result = NULL;
3039 switch (peek()) {
3040 case Token::THIS: {
3041 Consume(Token::THIS);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003042 result = new(zone()) VariableProxy(isolate(), top_scope_->receiver());
Steve Blocka7e24c12009-10-30 11:49:00 +00003043 break;
3044 }
3045
3046 case Token::NULL_LITERAL:
3047 Consume(Token::NULL_LITERAL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003048 result = new(zone()) Literal(
3049 isolate(), isolate()->factory()->null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003050 break;
3051
3052 case Token::TRUE_LITERAL:
3053 Consume(Token::TRUE_LITERAL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003054 result = new(zone()) Literal(
3055 isolate(), isolate()->factory()->true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003056 break;
3057
3058 case Token::FALSE_LITERAL:
3059 Consume(Token::FALSE_LITERAL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003060 result = new(zone()) Literal(
3061 isolate(), isolate()->factory()->false_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003062 break;
3063
Steve Block1e0659c2011-05-24 12:43:12 +01003064 case Token::IDENTIFIER:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003065 case Token::FUTURE_STRICT_RESERVED_WORD: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003066 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003067 if (fni_ != NULL) fni_->PushVariableName(name);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003068 result = top_scope_->NewUnresolved(name,
3069 inside_with(),
3070 scanner().location().beg_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00003071 break;
3072 }
3073
3074 case Token::NUMBER: {
3075 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003076 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01003077 double value = StringToDouble(isolate()->unicode_cache(),
3078 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01003079 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003080 result = NewNumberLiteral(value);
3081 break;
3082 }
3083
3084 case Token::STRING: {
3085 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003086 Handle<String> symbol = GetSymbol(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003087 result = NewLiteral(symbol);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003088 if (fni_ != NULL) fni_->PushLiteralName(symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00003089 break;
3090 }
3091
3092 case Token::ASSIGN_DIV:
3093 result = ParseRegExpLiteral(true, CHECK_OK);
3094 break;
3095
3096 case Token::DIV:
3097 result = ParseRegExpLiteral(false, CHECK_OK);
3098 break;
3099
3100 case Token::LBRACK:
3101 result = ParseArrayLiteral(CHECK_OK);
3102 break;
3103
3104 case Token::LBRACE:
3105 result = ParseObjectLiteral(CHECK_OK);
3106 break;
3107
3108 case Token::LPAREN:
3109 Consume(Token::LPAREN);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003110 // Heuristically try to detect immediately called functions before
3111 // seeing the call parentheses.
3112 parenthesized_function_ = (peek() == Token::FUNCTION);
Steve Blocka7e24c12009-10-30 11:49:00 +00003113 result = ParseExpression(true, CHECK_OK);
3114 Expect(Token::RPAREN, CHECK_OK);
3115 break;
3116
3117 case Token::MOD:
3118 if (allow_natives_syntax_ || extension_ != NULL) {
3119 result = ParseV8Intrinsic(CHECK_OK);
3120 break;
3121 }
3122 // If we're not allowing special syntax we fall-through to the
3123 // default case.
3124
3125 default: {
Ben Murdochbb769b22010-08-11 14:56:33 +01003126 Token::Value tok = Next();
Steve Blocka7e24c12009-10-30 11:49:00 +00003127 ReportUnexpectedToken(tok);
3128 *ok = false;
3129 return NULL;
3130 }
3131 }
3132
3133 return result;
3134}
3135
3136
Leon Clarke4515c472010-02-03 11:58:03 +00003137void Parser::BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* values,
3138 Handle<FixedArray> literals,
3139 bool* is_simple,
3140 int* depth) {
3141 // Fill in the literals.
3142 // Accumulate output values in local variables.
3143 bool is_simple_acc = true;
3144 int depth_acc = 1;
3145 for (int i = 0; i < values->length(); i++) {
3146 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
3147 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3148 depth_acc = m_literal->depth() + 1;
3149 }
3150 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
3151 if (boilerplate_value->IsUndefined()) {
3152 literals->set_the_hole(i);
3153 is_simple_acc = false;
3154 } else {
3155 literals->set(i, *boilerplate_value);
3156 }
3157 }
3158
3159 *is_simple = is_simple_acc;
3160 *depth = depth_acc;
3161}
3162
3163
Steve Blocka7e24c12009-10-30 11:49:00 +00003164Expression* Parser::ParseArrayLiteral(bool* ok) {
3165 // ArrayLiteral ::
3166 // '[' Expression? (',' Expression?)* ']'
3167
Ben Murdoch257744e2011-11-30 15:57:28 +00003168 ZoneList<Expression*>* values = new(zone()) ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003169 Expect(Token::LBRACK, CHECK_OK);
3170 while (peek() != Token::RBRACK) {
3171 Expression* elem;
3172 if (peek() == Token::COMMA) {
3173 elem = GetLiteralTheHole();
3174 } else {
3175 elem = ParseAssignmentExpression(true, CHECK_OK);
3176 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003177 values->Add(elem);
Steve Blocka7e24c12009-10-30 11:49:00 +00003178 if (peek() != Token::RBRACK) {
3179 Expect(Token::COMMA, CHECK_OK);
3180 }
3181 }
3182 Expect(Token::RBRACK, CHECK_OK);
3183
3184 // Update the scope information before the pre-parsing bailout.
Steve Block44f0eee2011-05-26 01:26:41 +01003185 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003186
Steve Blocka7e24c12009-10-30 11:49:00 +00003187 // Allocate a fixed array with all the literals.
3188 Handle<FixedArray> literals =
Steve Block44f0eee2011-05-26 01:26:41 +01003189 isolate()->factory()->NewFixedArray(values->length(), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003190
3191 // Fill in the literals.
3192 bool is_simple = true;
3193 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003194 for (int i = 0, n = values->length(); i < n; i++) {
3195 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
Steve Blocka7e24c12009-10-30 11:49:00 +00003196 if (m_literal != NULL && m_literal->depth() + 1 > depth) {
3197 depth = m_literal->depth() + 1;
3198 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003199 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00003200 if (boilerplate_value->IsUndefined()) {
3201 literals->set_the_hole(i);
3202 is_simple = false;
3203 } else {
3204 literals->set(i, *boilerplate_value);
3205 }
3206 }
3207
Iain Merrick75681382010-08-19 15:07:18 +01003208 // Simple and shallow arrays can be lazily copied, we transform the
3209 // elements array to a copy-on-write array.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003210 if (is_simple && depth == 1 && values->length() > 0) {
Steve Block44f0eee2011-05-26 01:26:41 +01003211 literals->set_map(isolate()->heap()->fixed_cow_array_map());
Iain Merrick75681382010-08-19 15:07:18 +01003212 }
3213
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003214 return new(zone()) ArrayLiteral(
3215 isolate(), literals, values, literal_index, is_simple, depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003216}
3217
3218
3219bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
3220 return property != NULL &&
3221 property->kind() != ObjectLiteral::Property::PROTOTYPE;
3222}
3223
3224
3225bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003226 if (expression->AsLiteral() != NULL) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003227 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3228 return lit != NULL && lit->is_simple();
3229}
3230
Iain Merrick75681382010-08-19 15:07:18 +01003231
3232bool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
3233 Expression* value) {
3234 // If value is a literal the property value is already set in the
3235 // boilerplate object.
3236 if (value->AsLiteral() != NULL) return false;
3237 // If value is a materialized literal the property value is already set
3238 // in the boilerplate object if it is simple.
3239 if (CompileTimeValue::IsCompileTimeValue(value)) return false;
3240 return true;
3241}
3242
3243
Steve Blocka7e24c12009-10-30 11:49:00 +00003244Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
3245 ASSERT(IsCompileTimeValue(expression));
Steve Block44f0eee2011-05-26 01:26:41 +01003246 Handle<FixedArray> result = FACTORY->NewFixedArray(2, TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003247 ObjectLiteral* object_literal = expression->AsObjectLiteral();
3248 if (object_literal != NULL) {
3249 ASSERT(object_literal->is_simple());
Steve Block6ded16b2010-05-10 14:33:55 +01003250 if (object_literal->fast_elements()) {
3251 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3252 } else {
3253 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3254 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003255 result->set(kElementsSlot, *object_literal->constant_properties());
3256 } else {
3257 ArrayLiteral* array_literal = expression->AsArrayLiteral();
3258 ASSERT(array_literal != NULL && array_literal->is_simple());
3259 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
Leon Clarkee46be812010-01-19 14:06:41 +00003260 result->set(kElementsSlot, *array_literal->constant_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00003261 }
3262 return result;
3263}
3264
3265
3266CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
3267 Smi* type_value = Smi::cast(value->get(kTypeSlot));
3268 return static_cast<Type>(type_value->value());
3269}
3270
3271
3272Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3273 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3274}
3275
3276
3277Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
3278 if (expression->AsLiteral() != NULL) {
3279 return expression->AsLiteral()->handle();
3280 }
3281 if (CompileTimeValue::IsCompileTimeValue(expression)) {
3282 return CompileTimeValue::GetValue(expression);
3283 }
Steve Block44f0eee2011-05-26 01:26:41 +01003284 return isolate()->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003285}
3286
Steve Block1e0659c2011-05-24 12:43:12 +01003287// Defined in ast.cc
3288bool IsEqualString(void* first, void* second);
3289bool IsEqualNumber(void* first, void* second);
3290
3291
3292// Validation per 11.1.5 Object Initialiser
3293class ObjectLiteralPropertyChecker {
3294 public:
3295 ObjectLiteralPropertyChecker(Parser* parser, bool strict) :
3296 props(&IsEqualString),
3297 elems(&IsEqualNumber),
3298 parser_(parser),
3299 strict_(strict) {
3300 }
3301
3302 void CheckProperty(
3303 ObjectLiteral::Property* property,
3304 Scanner::Location loc,
3305 bool* ok);
3306
3307 private:
3308 enum PropertyKind {
3309 kGetAccessor = 0x01,
3310 kSetAccessor = 0x02,
3311 kAccessor = kGetAccessor | kSetAccessor,
3312 kData = 0x04
3313 };
3314
3315 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) {
3316 switch (property->kind()) {
3317 case ObjectLiteral::Property::GETTER:
3318 return kGetAccessor;
3319 case ObjectLiteral::Property::SETTER:
3320 return kSetAccessor;
3321 default:
3322 return kData;
3323 }
3324 }
3325
3326 HashMap props;
3327 HashMap elems;
3328 Parser* parser_;
3329 bool strict_;
3330};
3331
3332
3333void ObjectLiteralPropertyChecker::CheckProperty(
3334 ObjectLiteral::Property* property,
3335 Scanner::Location loc,
3336 bool* ok) {
3337
3338 ASSERT(property != NULL);
3339
3340 Literal *lit = property->key();
3341 Handle<Object> handle = lit->handle();
3342
3343 uint32_t hash;
3344 HashMap* map;
3345 void* key;
3346
3347 if (handle->IsSymbol()) {
3348 Handle<String> name(String::cast(*handle));
3349 if (name->AsArrayIndex(&hash)) {
Steve Block44f0eee2011-05-26 01:26:41 +01003350 Handle<Object> key_handle = FACTORY->NewNumberFromUint(hash);
Steve Block1e0659c2011-05-24 12:43:12 +01003351 key = key_handle.location();
3352 map = &elems;
3353 } else {
3354 key = handle.location();
3355 hash = name->Hash();
3356 map = &props;
3357 }
3358 } else if (handle->ToArrayIndex(&hash)) {
3359 key = handle.location();
3360 map = &elems;
3361 } else {
3362 ASSERT(handle->IsNumber());
3363 double num = handle->Number();
3364 char arr[100];
3365 Vector<char> buffer(arr, ARRAY_SIZE(arr));
3366 const char* str = DoubleToCString(num, buffer);
Steve Block44f0eee2011-05-26 01:26:41 +01003367 Handle<String> name = FACTORY->NewStringFromAscii(CStrVector(str));
Steve Block1e0659c2011-05-24 12:43:12 +01003368 key = name.location();
3369 hash = name->Hash();
3370 map = &props;
3371 }
3372
3373 // Lookup property previously defined, if any.
3374 HashMap::Entry* entry = map->Lookup(key, hash, true);
3375 intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
3376 intptr_t curr = GetPropertyKind(property);
3377
3378 // Duplicate data properties are illegal in strict mode.
3379 if (strict_ && (curr & prev & kData) != 0) {
3380 parser_->ReportMessageAt(loc, "strict_duplicate_property",
3381 Vector<const char*>::empty());
3382 *ok = false;
3383 return;
3384 }
3385 // Data property conflicting with an accessor.
3386 if (((curr & kData) && (prev & kAccessor)) ||
3387 ((prev & kData) && (curr & kAccessor))) {
3388 parser_->ReportMessageAt(loc, "accessor_data_property",
3389 Vector<const char*>::empty());
3390 *ok = false;
3391 return;
3392 }
3393 // Two accessors of the same type conflicting
3394 if ((curr & prev & kAccessor) != 0) {
3395 parser_->ReportMessageAt(loc, "accessor_get_set",
3396 Vector<const char*>::empty());
3397 *ok = false;
3398 return;
3399 }
3400
3401 // Update map
3402 entry->value = reinterpret_cast<void*> (prev | curr);
3403 *ok = true;
3404}
3405
Steve Blocka7e24c12009-10-30 11:49:00 +00003406
Leon Clarke4515c472010-02-03 11:58:03 +00003407void Parser::BuildObjectLiteralConstantProperties(
3408 ZoneList<ObjectLiteral::Property*>* properties,
3409 Handle<FixedArray> constant_properties,
3410 bool* is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003411 bool* fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003412 int* depth) {
3413 int position = 0;
3414 // Accumulate the value in local variables and store it at the end.
3415 bool is_simple_acc = true;
3416 int depth_acc = 1;
Steve Block6ded16b2010-05-10 14:33:55 +01003417 uint32_t max_element_index = 0;
3418 uint32_t elements = 0;
Leon Clarke4515c472010-02-03 11:58:03 +00003419 for (int i = 0; i < properties->length(); i++) {
3420 ObjectLiteral::Property* property = properties->at(i);
3421 if (!IsBoilerplateProperty(property)) {
3422 is_simple_acc = false;
3423 continue;
3424 }
3425 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
3426 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
3427 depth_acc = m_literal->depth() + 1;
3428 }
3429
3430 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
3431 // value for COMPUTED properties, the real value is filled in at
3432 // runtime. The enumeration order is maintained.
3433 Handle<Object> key = property->key()->handle();
3434 Handle<Object> value = GetBoilerplateValue(property->value());
3435 is_simple_acc = is_simple_acc && !value->IsUndefined();
3436
Steve Block6ded16b2010-05-10 14:33:55 +01003437 // Keep track of the number of elements in the object literal and
3438 // the largest element index. If the largest element index is
3439 // much larger than the number of elements, creating an object
3440 // literal with fast elements will be a waste of space.
3441 uint32_t element_index = 0;
3442 if (key->IsString()
3443 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
3444 && element_index > max_element_index) {
3445 max_element_index = element_index;
3446 elements++;
3447 } else if (key->IsSmi()) {
3448 int key_value = Smi::cast(*key)->value();
3449 if (key_value > 0
3450 && static_cast<uint32_t>(key_value) > max_element_index) {
3451 max_element_index = key_value;
3452 }
3453 elements++;
3454 }
3455
Leon Clarke4515c472010-02-03 11:58:03 +00003456 // Add name, value pair to the fixed array.
3457 constant_properties->set(position++, *key);
3458 constant_properties->set(position++, *value);
3459 }
Steve Block6ded16b2010-05-10 14:33:55 +01003460 *fast_elements =
3461 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
Leon Clarke4515c472010-02-03 11:58:03 +00003462 *is_simple = is_simple_acc;
3463 *depth = depth_acc;
3464}
3465
3466
Ben Murdochbb769b22010-08-11 14:56:33 +01003467ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
3468 bool* ok) {
3469 // Special handling of getter and setter syntax:
3470 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3471 // We have already read the "get" or "set" keyword.
3472 Token::Value next = Next();
Steve Block9fac8402011-05-12 15:51:54 +01003473 bool is_keyword = Token::IsKeyword(next);
3474 if (next == Token::IDENTIFIER || next == Token::NUMBER ||
Steve Block1e0659c2011-05-24 12:43:12 +01003475 next == Token::FUTURE_RESERVED_WORD ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003476 next == Token::FUTURE_STRICT_RESERVED_WORD ||
Steve Block9fac8402011-05-12 15:51:54 +01003477 next == Token::STRING || is_keyword) {
3478 Handle<String> name;
3479 if (is_keyword) {
Steve Block44f0eee2011-05-26 01:26:41 +01003480 name = isolate_->factory()->LookupAsciiSymbol(Token::String(next));
Steve Block9fac8402011-05-12 15:51:54 +01003481 } else {
3482 name = GetSymbol(CHECK_OK);
3483 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003484 FunctionLiteral* value =
3485 ParseFunctionLiteral(name,
Steve Block1e0659c2011-05-24 12:43:12 +01003486 false, // reserved words are allowed here
Ben Murdochbb769b22010-08-11 14:56:33 +01003487 RelocInfo::kNoPosition,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003488 FunctionLiteral::ANONYMOUS_EXPRESSION,
Ben Murdochbb769b22010-08-11 14:56:33 +01003489 CHECK_OK);
Steve Block9fac8402011-05-12 15:51:54 +01003490 // Allow any number of parameters for compatiabilty with JSC.
3491 // Specification only allows zero parameters for get and one for set.
Ben Murdochbb769b22010-08-11 14:56:33 +01003492 ObjectLiteral::Property* property =
Ben Murdoch8b112d22011-06-08 16:22:53 +01003493 new(zone()) ObjectLiteral::Property(is_getter, value);
Ben Murdochbb769b22010-08-11 14:56:33 +01003494 return property;
3495 } else {
3496 ReportUnexpectedToken(next);
3497 *ok = false;
3498 return NULL;
3499 }
3500}
3501
3502
Steve Blocka7e24c12009-10-30 11:49:00 +00003503Expression* Parser::ParseObjectLiteral(bool* ok) {
3504 // ObjectLiteral ::
3505 // '{' (
Ben Murdochbb769b22010-08-11 14:56:33 +01003506 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3507 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
Steve Blocka7e24c12009-10-30 11:49:00 +00003508 // )*[','] '}'
3509
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003510 ZoneList<ObjectLiteral::Property*>* properties =
Ben Murdoch257744e2011-11-30 15:57:28 +00003511 new(zone()) ZoneList<ObjectLiteral::Property*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003512 int number_of_boilerplate_properties = 0;
Steve Block44f0eee2011-05-26 01:26:41 +01003513 bool has_function = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003514
Steve Block44f0eee2011-05-26 01:26:41 +01003515 ObjectLiteralPropertyChecker checker(this, top_scope_->is_strict_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01003516
Steve Blocka7e24c12009-10-30 11:49:00 +00003517 Expect(Token::LBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003518
Steve Blocka7e24c12009-10-30 11:49:00 +00003519 while (peek() != Token::RBRACE) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003520 if (fni_ != NULL) fni_->Enter();
3521
Steve Blocka7e24c12009-10-30 11:49:00 +00003522 Literal* key = NULL;
Ben Murdochbb769b22010-08-11 14:56:33 +01003523 Token::Value next = peek();
Steve Block1e0659c2011-05-24 12:43:12 +01003524
3525 // Location of the property name token
3526 Scanner::Location loc = scanner().peek_location();
3527
Ben Murdochbb769b22010-08-11 14:56:33 +01003528 switch (next) {
Steve Block1e0659c2011-05-24 12:43:12 +01003529 case Token::FUTURE_RESERVED_WORD:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003530 case Token::FUTURE_STRICT_RESERVED_WORD:
Steve Blocka7e24c12009-10-30 11:49:00 +00003531 case Token::IDENTIFIER: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003532 bool is_getter = false;
3533 bool is_setter = false;
3534 Handle<String> id =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003535 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003536 if (fni_ != NULL) fni_->PushLiteralName(id);
3537
Ben Murdochbb769b22010-08-11 14:56:33 +01003538 if ((is_getter || is_setter) && peek() != Token::COLON) {
Steve Block1e0659c2011-05-24 12:43:12 +01003539 // Update loc to point to the identifier
3540 loc = scanner().peek_location();
Steve Blocka7e24c12009-10-30 11:49:00 +00003541 ObjectLiteral::Property* property =
Ben Murdochbb769b22010-08-11 14:56:33 +01003542 ParseObjectLiteralGetSet(is_getter, CHECK_OK);
3543 if (IsBoilerplateProperty(property)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003544 number_of_boilerplate_properties++;
Ben Murdochbb769b22010-08-11 14:56:33 +01003545 }
Steve Block1e0659c2011-05-24 12:43:12 +01003546 // Validate the property.
3547 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003548 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003549 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003550
3551 if (fni_ != NULL) {
3552 fni_->Infer();
3553 fni_->Leave();
3554 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003555 continue; // restart the while
Steve Blocka7e24c12009-10-30 11:49:00 +00003556 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003557 // Failed to parse as get/set property, so it's just a property
3558 // called "get" or "set".
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003559 key = NewLiteral(id);
Steve Blocka7e24c12009-10-30 11:49:00 +00003560 break;
3561 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003562 case Token::STRING: {
3563 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003564 Handle<String> string = GetSymbol(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003565 if (fni_ != NULL) fni_->PushLiteralName(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003566 uint32_t index;
Iain Merrick75681382010-08-19 15:07:18 +01003567 if (!string.is_null() && string->AsArrayIndex(&index)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003568 key = NewNumberLiteral(index);
Ben Murdochbb769b22010-08-11 14:56:33 +01003569 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00003570 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003571 key = NewLiteral(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003572 break;
3573 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003574 case Token::NUMBER: {
3575 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003576 ASSERT(scanner().is_literal_ascii());
Ben Murdoch8b112d22011-06-08 16:22:53 +01003577 double value = StringToDouble(isolate()->unicode_cache(),
3578 scanner().literal_ascii_string(),
Steve Block9fac8402011-05-12 15:51:54 +01003579 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003580 key = NewNumberLiteral(value);
3581 break;
3582 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003583 default:
Ben Murdochbb769b22010-08-11 14:56:33 +01003584 if (Token::IsKeyword(next)) {
3585 Consume(next);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003586 Handle<String> string = GetSymbol(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003587 key = NewLiteral(string);
Ben Murdochbb769b22010-08-11 14:56:33 +01003588 } else {
3589 // Unexpected token.
3590 Token::Value next = Next();
3591 ReportUnexpectedToken(next);
3592 *ok = false;
3593 return NULL;
3594 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003595 }
3596
3597 Expect(Token::COLON, CHECK_OK);
3598 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
3599
3600 ObjectLiteral::Property* property =
Ben Murdoch8b112d22011-06-08 16:22:53 +01003601 new(zone()) ObjectLiteral::Property(key, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003602
Steve Block44f0eee2011-05-26 01:26:41 +01003603 // Mark object literals that contain function literals and pretenure the
3604 // literal so it can be added as a constant function property.
3605 if (value->AsFunctionLiteral() != NULL) {
3606 has_function = true;
3607 value->AsFunctionLiteral()->set_pretenure(true);
3608 }
3609
Steve Blocka7e24c12009-10-30 11:49:00 +00003610 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3611 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
Steve Block1e0659c2011-05-24 12:43:12 +01003612 // Validate the property
3613 checker.CheckProperty(property, loc, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003614 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003615
3616 // TODO(1240767): Consider allowing trailing comma.
3617 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003618
3619 if (fni_ != NULL) {
3620 fni_->Infer();
3621 fni_->Leave();
3622 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003623 }
3624 Expect(Token::RBRACE, CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003625
Steve Blocka7e24c12009-10-30 11:49:00 +00003626 // Computation of literal_index must happen before pre parse bailout.
Steve Block44f0eee2011-05-26 01:26:41 +01003627 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003628
Steve Block44f0eee2011-05-26 01:26:41 +01003629 Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray(
3630 number_of_boilerplate_properties * 2, TENURED);
Leon Clarke4515c472010-02-03 11:58:03 +00003631
Steve Blocka7e24c12009-10-30 11:49:00 +00003632 bool is_simple = true;
Steve Block6ded16b2010-05-10 14:33:55 +01003633 bool fast_elements = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003634 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003635 BuildObjectLiteralConstantProperties(properties,
Leon Clarke4515c472010-02-03 11:58:03 +00003636 constant_properties,
3637 &is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003638 &fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003639 &depth);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003640 return new(zone()) ObjectLiteral(isolate(),
3641 constant_properties,
3642 properties,
3643 literal_index,
3644 is_simple,
3645 fast_elements,
3646 depth,
3647 has_function);
Steve Blocka7e24c12009-10-30 11:49:00 +00003648}
3649
3650
3651Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003652 if (!scanner().ScanRegExpPattern(seen_equal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003653 Next();
3654 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3655 *ok = false;
3656 return NULL;
3657 }
3658
Steve Block44f0eee2011-05-26 01:26:41 +01003659 int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003660
Steve Block9fac8402011-05-12 15:51:54 +01003661 Handle<String> js_pattern = NextLiteralString(TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003662 scanner().ScanRegExpFlags();
Steve Block9fac8402011-05-12 15:51:54 +01003663 Handle<String> js_flags = NextLiteralString(TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003664 Next();
3665
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003666 return new(zone()) RegExpLiteral(
3667 isolate(), js_pattern, js_flags, literal_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00003668}
3669
3670
3671ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3672 // Arguments ::
3673 // '(' (AssignmentExpression)*[','] ')'
3674
Ben Murdoch257744e2011-11-30 15:57:28 +00003675 ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003676 Expect(Token::LPAREN, CHECK_OK);
3677 bool done = (peek() == Token::RPAREN);
3678 while (!done) {
3679 Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003680 result->Add(argument);
Steve Block053d10c2011-06-13 19:13:29 +01003681 if (result->length() > kMaxNumFunctionParameters) {
3682 ReportMessageAt(scanner().location(), "too_many_arguments",
3683 Vector<const char*>::empty());
3684 *ok = false;
3685 return NULL;
3686 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003687 done = (peek() == Token::RPAREN);
3688 if (!done) Expect(Token::COMMA, CHECK_OK);
3689 }
3690 Expect(Token::RPAREN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003691 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003692}
3693
3694
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003695FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
3696 bool name_is_strict_reserved,
Steve Blocka7e24c12009-10-30 11:49:00 +00003697 int function_token_position,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003698 FunctionLiteral::Type type,
Steve Blocka7e24c12009-10-30 11:49:00 +00003699 bool* ok) {
3700 // Function ::
3701 // '(' FormalParameterList? ')' '{' FunctionBody '}'
Steve Blocka7e24c12009-10-30 11:49:00 +00003702
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003703 // Anonymous functions were passed either the empty symbol or a null
3704 // handle as the function name. Remember if we were passed a non-empty
3705 // handle to decide whether to invoke function name inference.
3706 bool should_infer_name = function_name.is_null();
3707
3708 // We want a non-null handle as the function name.
3709 if (should_infer_name) {
3710 function_name = isolate()->factory()->empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003711 }
3712
3713 int num_parameters = 0;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003714 // Function declarations are function scoped in normal mode, so they are
3715 // hoisted. In harmony block scoping mode they are block scoped, so they
3716 // are not hoisted.
3717 Scope* scope = (type == FunctionLiteral::DECLARATION &&
3718 !harmony_block_scoping_)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003719 ? NewScope(top_scope_->DeclarationScope(), Scope::FUNCTION_SCOPE, false)
3720 : NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
Ben Murdoch257744e2011-11-30 15:57:28 +00003721 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003722 int materialized_literal_count;
3723 int expected_property_count;
3724 int start_pos;
3725 int end_pos;
3726 bool only_simple_this_property_assignments;
3727 Handle<FixedArray> this_property_assignments;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003728 bool has_duplicate_parameters = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003729 // Parse function body.
Ben Murdoch8b112d22011-06-08 16:22:53 +01003730 { LexicalScope lexical_scope(this, scope, isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003731 top_scope_->SetScopeName(function_name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003732
3733 // FormalParameterList ::
3734 // '(' (Identifier)*[','] ')'
3735 Expect(Token::LPAREN, CHECK_OK);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003736 start_pos = scanner().location().beg_pos;
Ben Murdoch257744e2011-11-30 15:57:28 +00003737 Scanner::Location name_loc = Scanner::Location::invalid();
3738 Scanner::Location dupe_loc = Scanner::Location::invalid();
3739 Scanner::Location reserved_loc = Scanner::Location::invalid();
Steve Block1e0659c2011-05-24 12:43:12 +01003740
Steve Blocka7e24c12009-10-30 11:49:00 +00003741 bool done = (peek() == Token::RPAREN);
3742 while (!done) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003743 bool is_strict_reserved = false;
Steve Block1e0659c2011-05-24 12:43:12 +01003744 Handle<String> param_name =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003745 ParseIdentifierOrStrictReservedWord(&is_strict_reserved,
3746 CHECK_OK);
Steve Block1e0659c2011-05-24 12:43:12 +01003747
3748 // Store locations for possible future error reports.
3749 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
3750 name_loc = scanner().location();
3751 }
3752 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003753 has_duplicate_parameters = true;
Steve Block1e0659c2011-05-24 12:43:12 +01003754 dupe_loc = scanner().location();
3755 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003756 if (!reserved_loc.IsValid() && is_strict_reserved) {
Steve Block1e0659c2011-05-24 12:43:12 +01003757 reserved_loc = scanner().location();
3758 }
3759
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003760 top_scope_->DeclareParameter(param_name);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003761 num_parameters++;
Steve Block1e0659c2011-05-24 12:43:12 +01003762 if (num_parameters > kMaxNumFunctionParameters) {
3763 ReportMessageAt(scanner().location(), "too_many_parameters",
3764 Vector<const char*>::empty());
3765 *ok = false;
3766 return NULL;
3767 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003768 done = (peek() == Token::RPAREN);
3769 if (!done) Expect(Token::COMMA, CHECK_OK);
3770 }
3771 Expect(Token::RPAREN, CHECK_OK);
3772
3773 Expect(Token::LBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003774
3775 // If we have a named function expression, we add a local variable
3776 // declaration to the body of the function with the name of the
3777 // function and let it refer to the function itself (closure).
3778 // NOTE: We create a proxy and resolve it here so that in the
3779 // future we can change the AST to only refer to VariableProxies
3780 // instead of Variables and Proxis as is the case now.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003781 if (type == FunctionLiteral::NAMED_EXPRESSION) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003782 Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
3783 VariableProxy* fproxy =
3784 top_scope_->NewUnresolved(function_name, inside_with());
3785 fproxy->BindTo(fvar);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003786 body->Add(new(zone()) ExpressionStatement(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003787 new(zone()) Assignment(isolate(),
3788 Token::INIT_CONST,
3789 fproxy,
3790 new(zone()) ThisFunction(isolate()),
3791 RelocInfo::kNoPosition)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003792 }
3793
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003794 // Determine if the function will be lazily compiled. The mode can only
3795 // be PARSE_LAZILY if the --lazy flag is true. We will not lazily
3796 // compile if we do not have preparser data for the function.
Ben Murdochb8e0da22011-05-16 14:20:40 +01003797 bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
3798 top_scope_->outer_scope()->is_global_scope() &&
3799 top_scope_->HasTrivialOuterContext() &&
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003800 !parenthesized_function_ &&
3801 pre_data() != NULL);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003802 parenthesized_function_ = false; // The bit was set for this function only.
Steve Blocka7e24c12009-10-30 11:49:00 +00003803
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003804 if (is_lazily_compiled) {
3805 int function_block_pos = scanner().location().beg_pos;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003806 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos);
Leon Clarkeac952652010-07-15 11:15:24 +01003807 if (!entry.is_valid()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003808 // There is no preparser data for the function, we will not lazily
3809 // compile after all.
3810 is_lazily_compiled = false;
3811 } else {
3812 end_pos = entry.end_pos();
3813 if (end_pos <= function_block_pos) {
3814 // End position greater than end of stream is safe, and hard to check.
3815 ReportInvalidPreparseData(function_name, CHECK_OK);
3816 }
3817 isolate()->counters()->total_preparse_skipped()->Increment(
3818 end_pos - function_block_pos);
3819 // Seek to position just before terminal '}'.
3820 scanner().SeekForward(end_pos - 1);
3821 materialized_literal_count = entry.literal_count();
3822 expected_property_count = entry.property_count();
3823 if (entry.strict_mode()) top_scope_->EnableStrictMode();
3824 only_simple_this_property_assignments = false;
3825 this_property_assignments = isolate()->factory()->empty_fixed_array();
3826 Expect(Token::RBRACE, CHECK_OK);
Leon Clarkeac952652010-07-15 11:15:24 +01003827 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003828 }
3829
3830 if (!is_lazily_compiled) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003831 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
3832
Steve Block44f0eee2011-05-26 01:26:41 +01003833 materialized_literal_count = lexical_scope.materialized_literal_count();
3834 expected_property_count = lexical_scope.expected_property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003835 only_simple_this_property_assignments =
Steve Block44f0eee2011-05-26 01:26:41 +01003836 lexical_scope.only_simple_this_property_assignments();
3837 this_property_assignments = lexical_scope.this_property_assignments();
Steve Blocka7e24c12009-10-30 11:49:00 +00003838
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003839 Expect(Token::RBRACE, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003840 end_pos = scanner().location().end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003841 }
3842
Steve Block1e0659c2011-05-24 12:43:12 +01003843 // Validate strict mode.
Steve Block44f0eee2011-05-26 01:26:41 +01003844 if (top_scope_->is_strict_mode()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003845 if (IsEvalOrArguments(function_name)) {
Steve Block1e0659c2011-05-24 12:43:12 +01003846 int position = function_token_position != RelocInfo::kNoPosition
3847 ? function_token_position
3848 : (start_pos > 0 ? start_pos - 1 : start_pos);
3849 Scanner::Location location = Scanner::Location(position, start_pos);
3850 ReportMessageAt(location,
3851 "strict_function_name", Vector<const char*>::empty());
3852 *ok = false;
3853 return NULL;
3854 }
3855 if (name_loc.IsValid()) {
3856 ReportMessageAt(name_loc, "strict_param_name",
3857 Vector<const char*>::empty());
3858 *ok = false;
3859 return NULL;
3860 }
3861 if (dupe_loc.IsValid()) {
3862 ReportMessageAt(dupe_loc, "strict_param_dupe",
3863 Vector<const char*>::empty());
3864 *ok = false;
3865 return NULL;
3866 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003867 if (name_is_strict_reserved) {
Steve Block1e0659c2011-05-24 12:43:12 +01003868 int position = function_token_position != RelocInfo::kNoPosition
3869 ? function_token_position
3870 : (start_pos > 0 ? start_pos - 1 : start_pos);
3871 Scanner::Location location = Scanner::Location(position, start_pos);
3872 ReportMessageAt(location, "strict_reserved_word",
3873 Vector<const char*>::empty());
3874 *ok = false;
3875 return NULL;
3876 }
3877 if (reserved_loc.IsValid()) {
3878 ReportMessageAt(reserved_loc, "strict_reserved_word",
3879 Vector<const char*>::empty());
3880 *ok = false;
3881 return NULL;
3882 }
3883 CheckOctalLiteral(start_pos, end_pos, CHECK_OK);
3884 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003885 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01003886
3887 FunctionLiteral* function_literal =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003888 new(zone()) FunctionLiteral(isolate(),
3889 function_name,
Ben Murdoch8b112d22011-06-08 16:22:53 +01003890 scope,
3891 body,
3892 materialized_literal_count,
3893 expected_property_count,
3894 only_simple_this_property_assignments,
3895 this_property_assignments,
3896 num_parameters,
3897 start_pos,
3898 end_pos,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003899 type,
3900 has_duplicate_parameters);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003901 function_literal->set_function_token_position(function_token_position);
3902
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003903 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003904 return function_literal;
Steve Blocka7e24c12009-10-30 11:49:00 +00003905}
3906
3907
3908Expression* Parser::ParseV8Intrinsic(bool* ok) {
3909 // CallRuntime ::
3910 // '%' Identifier Arguments
3911
3912 Expect(Token::MOD, CHECK_OK);
3913 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003914 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003915
3916 if (extension_ != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003917 // The extension structures are only accessible while parsing the
3918 // very first time not when reparsing because of lazy compilation.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003919 top_scope_->DeclarationScope()->ForceEagerCompilation();
Steve Blocka7e24c12009-10-30 11:49:00 +00003920 }
3921
Steve Block44f0eee2011-05-26 01:26:41 +01003922 const Runtime::Function* function = Runtime::FunctionForSymbol(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003923
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003924 // Check for built-in IS_VAR macro.
3925 if (function != NULL &&
3926 function->intrinsic_type == Runtime::RUNTIME &&
3927 function->function_id == Runtime::kIS_VAR) {
3928 // %IS_VAR(x) evaluates to x if x is a variable,
3929 // leads to a parse error otherwise. Could be implemented as an
3930 // inline function %_IS_VAR(x) to eliminate this special case.
3931 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
3932 return args->at(0);
3933 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00003934 ReportMessage("unable_to_parse", Vector<const char*>::empty());
Steve Block6ded16b2010-05-10 14:33:55 +01003935 *ok = false;
3936 return NULL;
Steve Block6ded16b2010-05-10 14:33:55 +01003937 }
3938 }
3939
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003940 // Check that the expected number of arguments are being passed.
3941 if (function != NULL &&
3942 function->nargs != -1 &&
3943 function->nargs != args->length()) {
3944 ReportMessage("illegal_access", Vector<const char*>::empty());
3945 *ok = false;
3946 return NULL;
3947 }
3948
3949 // We have a valid intrinsics call or a call to a builtin.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003950 return new(zone()) CallRuntime(isolate(), name, function, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00003951}
3952
3953
Steve Block1e0659c2011-05-24 12:43:12 +01003954bool Parser::peek_any_identifier() {
3955 Token::Value next = peek();
3956 return next == Token::IDENTIFIER ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003957 next == Token::FUTURE_RESERVED_WORD ||
3958 next == Token::FUTURE_STRICT_RESERVED_WORD;
Steve Block1e0659c2011-05-24 12:43:12 +01003959}
3960
3961
Steve Blocka7e24c12009-10-30 11:49:00 +00003962void Parser::Consume(Token::Value token) {
3963 Token::Value next = Next();
3964 USE(next);
3965 USE(token);
3966 ASSERT(next == token);
3967}
3968
3969
3970void Parser::Expect(Token::Value token, bool* ok) {
3971 Token::Value next = Next();
3972 if (next == token) return;
3973 ReportUnexpectedToken(next);
3974 *ok = false;
3975}
3976
3977
Leon Clarke4515c472010-02-03 11:58:03 +00003978bool Parser::Check(Token::Value token) {
3979 Token::Value next = peek();
3980 if (next == token) {
3981 Consume(next);
3982 return true;
3983 }
3984 return false;
3985}
3986
3987
Steve Blocka7e24c12009-10-30 11:49:00 +00003988void Parser::ExpectSemicolon(bool* ok) {
3989 // Check for automatic semicolon insertion according to
3990 // the rules given in ECMA-262, section 7.9, page 21.
3991 Token::Value tok = peek();
3992 if (tok == Token::SEMICOLON) {
3993 Next();
3994 return;
3995 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003996 if (scanner().HasAnyLineTerminatorBeforeNext() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00003997 tok == Token::RBRACE ||
3998 tok == Token::EOS) {
3999 return;
4000 }
4001 Expect(Token::SEMICOLON, ok);
4002}
4003
4004
4005Literal* Parser::GetLiteralUndefined() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004006 return NewLiteral(isolate()->factory()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00004007}
4008
4009
4010Literal* Parser::GetLiteralTheHole() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004011 return NewLiteral(isolate()->factory()->the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00004012}
4013
4014
4015Literal* Parser::GetLiteralNumber(double value) {
4016 return NewNumberLiteral(value);
4017}
4018
4019
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004020// Parses an identifier that is valid for the current scope, in particular it
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004021// fails on strict mode future reserved keywords in a strict scope.
Steve Blocka7e24c12009-10-30 11:49:00 +00004022Handle<String> Parser::ParseIdentifier(bool* ok) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004023 if (top_scope_->is_strict_mode()) {
4024 Expect(Token::IDENTIFIER, ok);
4025 } else if (!Check(Token::IDENTIFIER)) {
4026 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
4027 }
4028 if (!*ok) return Handle<String>();
4029 return GetSymbol(ok);
Steve Block1e0659c2011-05-24 12:43:12 +01004030}
4031
4032
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004033// Parses and identifier or a strict mode future reserved word, and indicate
4034// whether it is strict mode future reserved.
4035Handle<String> Parser::ParseIdentifierOrStrictReservedWord(
4036 bool* is_strict_reserved, bool* ok) {
4037 *is_strict_reserved = false;
4038 if (!Check(Token::IDENTIFIER)) {
4039 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
4040 *is_strict_reserved = true;
Steve Block1e0659c2011-05-24 12:43:12 +01004041 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004042 if (!*ok) return Handle<String>();
Iain Merrick9ac36c92010-09-13 15:29:50 +01004043 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00004044}
4045
Ben Murdochbb769b22010-08-11 14:56:33 +01004046
4047Handle<String> Parser::ParseIdentifierName(bool* ok) {
4048 Token::Value next = Next();
Steve Block1e0659c2011-05-24 12:43:12 +01004049 if (next != Token::IDENTIFIER &&
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004050 next != Token::FUTURE_RESERVED_WORD &&
4051 next != Token::FUTURE_STRICT_RESERVED_WORD &&
4052 !Token::IsKeyword(next)) {
Ben Murdochbb769b22010-08-11 14:56:33 +01004053 ReportUnexpectedToken(next);
4054 *ok = false;
4055 return Handle<String>();
4056 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01004057 return GetSymbol(ok);
Ben Murdochbb769b22010-08-11 14:56:33 +01004058}
4059
4060
Steve Block1e0659c2011-05-24 12:43:12 +01004061// Checks LHS expression for assignment and prefix/postfix increment/decrement
4062// in strict mode.
4063void Parser::CheckStrictModeLValue(Expression* expression,
4064 const char* error,
4065 bool* ok) {
Steve Block44f0eee2011-05-26 01:26:41 +01004066 ASSERT(top_scope_->is_strict_mode());
Steve Block1e0659c2011-05-24 12:43:12 +01004067 VariableProxy* lhs = expression != NULL
4068 ? expression->AsVariableProxy()
4069 : NULL;
4070
4071 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
4072 ReportMessage(error, Vector<const char*>::empty());
4073 *ok = false;
4074 }
4075}
4076
4077
Ben Murdoch257744e2011-11-30 15:57:28 +00004078// Checks whether an octal literal was last seen between beg_pos and end_pos.
4079// If so, reports an error. Only called for strict mode.
Steve Block1e0659c2011-05-24 12:43:12 +01004080void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
Ben Murdoch257744e2011-11-30 15:57:28 +00004081 Scanner::Location octal = scanner().octal_position();
4082 if (octal.IsValid() &&
4083 beg_pos <= octal.beg_pos &&
4084 octal.end_pos <= end_pos) {
4085 ReportMessageAt(octal, "strict_octal_literal",
Steve Block1e0659c2011-05-24 12:43:12 +01004086 Vector<const char*>::empty());
4087 scanner().clear_octal_position();
4088 *ok = false;
4089 }
4090}
4091
4092
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004093// This function reads an identifier name and determines whether or not it
Steve Block1e0659c2011-05-24 12:43:12 +01004094// is 'get' or 'set'.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004095Handle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get,
4096 bool* is_set,
4097 bool* ok) {
4098 Handle<String> result = ParseIdentifierName(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00004099 if (!*ok) return Handle<String>();
Steve Block9fac8402011-05-12 15:51:54 +01004100 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
4101 const char* token = scanner().literal_ascii_string().start();
4102 *is_get = strncmp(token, "get", 3) == 0;
4103 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00004104 }
Steve Block1e0659c2011-05-24 12:43:12 +01004105 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00004106}
4107
4108
4109// ----------------------------------------------------------------------------
4110// Parser support
4111
4112
4113bool Parser::TargetStackContainsLabel(Handle<String> label) {
4114 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4115 BreakableStatement* stat = t->node()->AsBreakableStatement();
4116 if (stat != NULL && ContainsLabel(stat->labels(), label))
4117 return true;
4118 }
4119 return false;
4120}
4121
4122
4123BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
4124 bool anonymous = label.is_null();
4125 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4126 BreakableStatement* stat = t->node()->AsBreakableStatement();
4127 if (stat == NULL) continue;
4128 if ((anonymous && stat->is_target_for_anonymous()) ||
4129 (!anonymous && ContainsLabel(stat->labels(), label))) {
4130 RegisterTargetUse(stat->break_target(), t->previous());
4131 return stat;
4132 }
4133 }
4134 return NULL;
4135}
4136
4137
4138IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
4139 bool* ok) {
4140 bool anonymous = label.is_null();
4141 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4142 IterationStatement* stat = t->node()->AsIterationStatement();
4143 if (stat == NULL) continue;
4144
4145 ASSERT(stat->is_target_for_anonymous());
4146 if (anonymous || ContainsLabel(stat->labels(), label)) {
4147 RegisterTargetUse(stat->continue_target(), t->previous());
4148 return stat;
4149 }
4150 }
4151 return NULL;
4152}
4153
4154
Ben Murdoch8b112d22011-06-08 16:22:53 +01004155void Parser::RegisterTargetUse(Label* target, Target* stop) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004156 // Register that a break target found at the given stop in the
4157 // target stack has been used from the top of the target stack. Add
4158 // the break target to any TargetCollectors passed on the stack.
4159 for (Target* t = target_stack_; t != stop; t = t->previous()) {
4160 TargetCollector* collector = t->node()->AsTargetCollector();
4161 if (collector != NULL) collector->AddTarget(target);
4162 }
4163}
4164
4165
4166Literal* Parser::NewNumberLiteral(double number) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004167 return NewLiteral(isolate()->factory()->NewNumber(number, TENURED));
Steve Blocka7e24c12009-10-30 11:49:00 +00004168}
4169
4170
4171Expression* Parser::NewThrowReferenceError(Handle<String> type) {
Steve Block44f0eee2011-05-26 01:26:41 +01004172 return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
Steve Blocka7e24c12009-10-30 11:49:00 +00004173 type, HandleVector<Object>(NULL, 0));
4174}
4175
4176
4177Expression* Parser::NewThrowSyntaxError(Handle<String> type,
4178 Handle<Object> first) {
4179 int argc = first.is_null() ? 0 : 1;
4180 Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
Steve Block44f0eee2011-05-26 01:26:41 +01004181 return NewThrowError(
4182 isolate()->factory()->MakeSyntaxError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00004183}
4184
4185
4186Expression* Parser::NewThrowTypeError(Handle<String> type,
4187 Handle<Object> first,
4188 Handle<Object> second) {
4189 ASSERT(!first.is_null() && !second.is_null());
4190 Handle<Object> elements[] = { first, second };
4191 Vector< Handle<Object> > arguments =
4192 HandleVector<Object>(elements, ARRAY_SIZE(elements));
Steve Block44f0eee2011-05-26 01:26:41 +01004193 return NewThrowError(
4194 isolate()->factory()->MakeTypeError_symbol(), type, arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00004195}
4196
4197
4198Expression* Parser::NewThrowError(Handle<String> constructor,
4199 Handle<String> type,
4200 Vector< Handle<Object> > arguments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004201 int argc = arguments.length();
Steve Block44f0eee2011-05-26 01:26:41 +01004202 Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc,
4203 TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004204 for (int i = 0; i < argc; i++) {
4205 Handle<Object> element = arguments[i];
4206 if (!element.is_null()) {
Steve Block1e0659c2011-05-24 12:43:12 +01004207 elements->set(i, *element);
Steve Blocka7e24c12009-10-30 11:49:00 +00004208 }
4209 }
Steve Block44f0eee2011-05-26 01:26:41 +01004210 Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(elements,
4211 TENURED);
Steve Block1e0659c2011-05-24 12:43:12 +01004212
Ben Murdoch257744e2011-11-30 15:57:28 +00004213 ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004214 args->Add(NewLiteral(type));
4215 args->Add(NewLiteral(array));
4216 CallRuntime* call_constructor = new(zone()) CallRuntime(isolate(),
4217 constructor,
4218 NULL,
4219 args);
4220 return new(zone()) Throw(isolate(),
4221 call_constructor,
4222 scanner().location().beg_pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00004223}
4224
Leon Clarke4515c472010-02-03 11:58:03 +00004225// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +00004226// Regular expressions
4227
4228
4229RegExpParser::RegExpParser(FlatStringReader* in,
4230 Handle<String>* error,
4231 bool multiline)
Steve Block44f0eee2011-05-26 01:26:41 +01004232 : isolate_(Isolate::Current()),
4233 error_(error),
4234 captures_(NULL),
4235 in_(in),
4236 current_(kEndMarker),
4237 next_pos_(0),
4238 capture_count_(0),
4239 has_more_(true),
4240 multiline_(multiline),
4241 simple_(false),
4242 contains_anchor_(false),
4243 is_scanned_for_captures_(false),
4244 failed_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004245 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004246}
4247
4248
4249uc32 RegExpParser::Next() {
4250 if (has_next()) {
4251 return in()->Get(next_pos_);
4252 } else {
4253 return kEndMarker;
4254 }
4255}
4256
4257
4258void RegExpParser::Advance() {
4259 if (next_pos_ < in()->length()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004260 StackLimitCheck check(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004261 if (check.HasOverflowed()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004262 ReportError(CStrVector(Isolate::kStackOverflowMessage));
4263 } else if (isolate()->zone()->excess_allocation()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004264 ReportError(CStrVector("Regular expression too large"));
4265 } else {
4266 current_ = in()->Get(next_pos_);
4267 next_pos_++;
4268 }
4269 } else {
4270 current_ = kEndMarker;
4271 has_more_ = false;
4272 }
4273}
4274
4275
4276void RegExpParser::Reset(int pos) {
4277 next_pos_ = pos;
4278 Advance();
4279}
4280
4281
4282void RegExpParser::Advance(int dist) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004283 next_pos_ += dist - 1;
4284 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00004285}
4286
4287
4288bool RegExpParser::simple() {
4289 return simple_;
4290}
4291
4292RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
4293 failed_ = true;
Steve Block44f0eee2011-05-26 01:26:41 +01004294 *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004295 // Zip to the end to make sure the no more input is read.
4296 current_ = kEndMarker;
4297 next_pos_ = in()->length();
4298 return NULL;
4299}
4300
4301
4302// Pattern ::
4303// Disjunction
4304RegExpTree* RegExpParser::ParsePattern() {
4305 RegExpTree* result = ParseDisjunction(CHECK_FAILED);
4306 ASSERT(!has_more());
4307 // If the result of parsing is a literal string atom, and it has the
4308 // same length as the input, then the atom is identical to the input.
4309 if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
4310 simple_ = true;
4311 }
4312 return result;
4313}
4314
4315
4316// Disjunction ::
4317// Alternative
4318// Alternative | Disjunction
4319// Alternative ::
4320// [empty]
4321// Term Alternative
4322// Term ::
4323// Assertion
4324// Atom
4325// Atom Quantifier
4326RegExpTree* RegExpParser::ParseDisjunction() {
4327 // Used to store current state while parsing subexpressions.
4328 RegExpParserState initial_state(NULL, INITIAL, 0);
4329 RegExpParserState* stored_state = &initial_state;
4330 // Cache the builder in a local variable for quick access.
4331 RegExpBuilder* builder = initial_state.builder();
4332 while (true) {
4333 switch (current()) {
4334 case kEndMarker:
4335 if (stored_state->IsSubexpression()) {
4336 // Inside a parenthesized group when hitting end of input.
4337 ReportError(CStrVector("Unterminated group") CHECK_FAILED);
4338 }
4339 ASSERT_EQ(INITIAL, stored_state->group_type());
4340 // Parsing completed successfully.
4341 return builder->ToRegExp();
4342 case ')': {
4343 if (!stored_state->IsSubexpression()) {
4344 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
4345 }
4346 ASSERT_NE(INITIAL, stored_state->group_type());
4347
4348 Advance();
4349 // End disjunction parsing and convert builder content to new single
4350 // regexp atom.
4351 RegExpTree* body = builder->ToRegExp();
4352
4353 int end_capture_index = captures_started();
4354
4355 int capture_index = stored_state->capture_index();
4356 SubexpressionType type = stored_state->group_type();
4357
4358 // Restore previous state.
4359 stored_state = stored_state->previous_state();
4360 builder = stored_state->builder();
4361
4362 // Build result of subexpression.
4363 if (type == CAPTURE) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01004364 RegExpCapture* capture = new(zone()) RegExpCapture(body, capture_index);
Steve Blocka7e24c12009-10-30 11:49:00 +00004365 captures_->at(capture_index - 1) = capture;
4366 body = capture;
4367 } else if (type != GROUPING) {
4368 ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
4369 bool is_positive = (type == POSITIVE_LOOKAHEAD);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004370 body = new(zone()) RegExpLookahead(body,
Steve Blocka7e24c12009-10-30 11:49:00 +00004371 is_positive,
4372 end_capture_index - capture_index,
4373 capture_index);
4374 }
4375 builder->AddAtom(body);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004376 // For compatability with JSC and ES3, we allow quantifiers after
4377 // lookaheads, and break in all cases.
Steve Blocka7e24c12009-10-30 11:49:00 +00004378 break;
4379 }
4380 case '|': {
4381 Advance();
4382 builder->NewAlternative();
4383 continue;
4384 }
4385 case '*':
4386 case '+':
4387 case '?':
4388 return ReportError(CStrVector("Nothing to repeat"));
4389 case '^': {
4390 Advance();
4391 if (multiline_) {
4392 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004393 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE));
Steve Blocka7e24c12009-10-30 11:49:00 +00004394 } else {
4395 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004396 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT));
Steve Blocka7e24c12009-10-30 11:49:00 +00004397 set_contains_anchor();
4398 }
4399 continue;
4400 }
4401 case '$': {
4402 Advance();
4403 RegExpAssertion::Type type =
4404 multiline_ ? RegExpAssertion::END_OF_LINE :
4405 RegExpAssertion::END_OF_INPUT;
Ben Murdoch8b112d22011-06-08 16:22:53 +01004406 builder->AddAssertion(new(zone()) RegExpAssertion(type));
Steve Blocka7e24c12009-10-30 11:49:00 +00004407 continue;
4408 }
4409 case '.': {
4410 Advance();
4411 // everything except \x0a, \x0d, \u2028 and \u2029
Ben Murdoch257744e2011-11-30 15:57:28 +00004412 ZoneList<CharacterRange>* ranges =
4413 new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004414 CharacterRange::AddClassEscape('.', ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004415 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004416 builder->AddAtom(atom);
4417 break;
4418 }
4419 case '(': {
4420 SubexpressionType type = CAPTURE;
4421 Advance();
4422 if (current() == '?') {
4423 switch (Next()) {
4424 case ':':
4425 type = GROUPING;
4426 break;
4427 case '=':
4428 type = POSITIVE_LOOKAHEAD;
4429 break;
4430 case '!':
4431 type = NEGATIVE_LOOKAHEAD;
4432 break;
4433 default:
4434 ReportError(CStrVector("Invalid group") CHECK_FAILED);
4435 break;
4436 }
4437 Advance(2);
4438 } else {
4439 if (captures_ == NULL) {
Ben Murdoch257744e2011-11-30 15:57:28 +00004440 captures_ = new(zone()) ZoneList<RegExpCapture*>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004441 }
4442 if (captures_started() >= kMaxCaptures) {
4443 ReportError(CStrVector("Too many captures") CHECK_FAILED);
4444 }
4445 captures_->Add(NULL);
4446 }
4447 // Store current state and begin new disjunction parsing.
Ben Murdoch8b112d22011-06-08 16:22:53 +01004448 stored_state = new(zone()) RegExpParserState(stored_state,
Steve Blocka7e24c12009-10-30 11:49:00 +00004449 type,
4450 captures_started());
4451 builder = stored_state->builder();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004452 continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00004453 }
4454 case '[': {
4455 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
4456 builder->AddAtom(atom);
4457 break;
4458 }
4459 // Atom ::
4460 // \ AtomEscape
4461 case '\\':
4462 switch (Next()) {
4463 case kEndMarker:
4464 return ReportError(CStrVector("\\ at end of pattern"));
4465 case 'b':
4466 Advance(2);
4467 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004468 new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004469 continue;
4470 case 'B':
4471 Advance(2);
4472 builder->AddAssertion(
Ben Murdoch8b112d22011-06-08 16:22:53 +01004473 new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
Steve Blocka7e24c12009-10-30 11:49:00 +00004474 continue;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004475 // AtomEscape ::
4476 // CharacterClassEscape
4477 //
4478 // CharacterClassEscape :: one of
4479 // d D s S w W
Steve Blocka7e24c12009-10-30 11:49:00 +00004480 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
4481 uc32 c = Next();
4482 Advance(2);
Ben Murdoch257744e2011-11-30 15:57:28 +00004483 ZoneList<CharacterRange>* ranges =
4484 new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004485 CharacterRange::AddClassEscape(c, ranges);
Ben Murdoch8b112d22011-06-08 16:22:53 +01004486 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004487 builder->AddAtom(atom);
4488 break;
4489 }
4490 case '1': case '2': case '3': case '4': case '5': case '6':
4491 case '7': case '8': case '9': {
4492 int index = 0;
4493 if (ParseBackReferenceIndex(&index)) {
4494 RegExpCapture* capture = NULL;
4495 if (captures_ != NULL && index <= captures_->length()) {
4496 capture = captures_->at(index - 1);
4497 }
4498 if (capture == NULL) {
4499 builder->AddEmpty();
4500 break;
4501 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01004502 RegExpTree* atom = new(zone()) RegExpBackReference(capture);
Steve Blocka7e24c12009-10-30 11:49:00 +00004503 builder->AddAtom(atom);
4504 break;
4505 }
4506 uc32 first_digit = Next();
4507 if (first_digit == '8' || first_digit == '9') {
4508 // Treat as identity escape
4509 builder->AddCharacter(first_digit);
4510 Advance(2);
4511 break;
4512 }
4513 }
4514 // FALLTHROUGH
4515 case '0': {
4516 Advance();
4517 uc32 octal = ParseOctalLiteral();
4518 builder->AddCharacter(octal);
4519 break;
4520 }
4521 // ControlEscape :: one of
4522 // f n r t v
4523 case 'f':
4524 Advance(2);
4525 builder->AddCharacter('\f');
4526 break;
4527 case 'n':
4528 Advance(2);
4529 builder->AddCharacter('\n');
4530 break;
4531 case 'r':
4532 Advance(2);
4533 builder->AddCharacter('\r');
4534 break;
4535 case 't':
4536 Advance(2);
4537 builder->AddCharacter('\t');
4538 break;
4539 case 'v':
4540 Advance(2);
4541 builder->AddCharacter('\v');
4542 break;
4543 case 'c': {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004544 Advance();
4545 uc32 controlLetter = Next();
4546 // Special case if it is an ASCII letter.
4547 // Convert lower case letters to uppercase.
4548 uc32 letter = controlLetter & ~('a' ^ 'A');
4549 if (letter < 'A' || 'Z' < letter) {
4550 // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
4551 // This is outside the specification. We match JSC in
4552 // reading the backslash as a literal character instead
4553 // of as starting an escape.
4554 builder->AddCharacter('\\');
4555 } else {
4556 Advance(2);
4557 builder->AddCharacter(controlLetter & 0x1f);
4558 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004559 break;
4560 }
4561 case 'x': {
4562 Advance(2);
4563 uc32 value;
4564 if (ParseHexEscape(2, &value)) {
4565 builder->AddCharacter(value);
4566 } else {
4567 builder->AddCharacter('x');
4568 }
4569 break;
4570 }
4571 case 'u': {
4572 Advance(2);
4573 uc32 value;
4574 if (ParseHexEscape(4, &value)) {
4575 builder->AddCharacter(value);
4576 } else {
4577 builder->AddCharacter('u');
4578 }
4579 break;
4580 }
4581 default:
4582 // Identity escape.
4583 builder->AddCharacter(Next());
4584 Advance(2);
4585 break;
4586 }
4587 break;
4588 case '{': {
4589 int dummy;
4590 if (ParseIntervalQuantifier(&dummy, &dummy)) {
4591 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
4592 }
4593 // fallthrough
4594 }
4595 default:
4596 builder->AddCharacter(current());
4597 Advance();
4598 break;
4599 } // end switch(current())
4600
4601 int min;
4602 int max;
4603 switch (current()) {
4604 // QuantifierPrefix ::
4605 // *
4606 // +
4607 // ?
4608 // {
4609 case '*':
4610 min = 0;
4611 max = RegExpTree::kInfinity;
4612 Advance();
4613 break;
4614 case '+':
4615 min = 1;
4616 max = RegExpTree::kInfinity;
4617 Advance();
4618 break;
4619 case '?':
4620 min = 0;
4621 max = 1;
4622 Advance();
4623 break;
4624 case '{':
4625 if (ParseIntervalQuantifier(&min, &max)) {
4626 if (max < min) {
4627 ReportError(CStrVector("numbers out of order in {} quantifier.")
4628 CHECK_FAILED);
4629 }
4630 break;
4631 } else {
4632 continue;
4633 }
4634 default:
4635 continue;
4636 }
Leon Clarkee46be812010-01-19 14:06:41 +00004637 RegExpQuantifier::Type type = RegExpQuantifier::GREEDY;
Steve Blocka7e24c12009-10-30 11:49:00 +00004638 if (current() == '?') {
Leon Clarkee46be812010-01-19 14:06:41 +00004639 type = RegExpQuantifier::NON_GREEDY;
4640 Advance();
4641 } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
4642 // FLAG_regexp_possessive_quantifier is a debug-only flag.
4643 type = RegExpQuantifier::POSSESSIVE;
Steve Blocka7e24c12009-10-30 11:49:00 +00004644 Advance();
4645 }
Leon Clarkee46be812010-01-19 14:06:41 +00004646 builder->AddQuantifierToAtom(min, max, type);
Steve Blocka7e24c12009-10-30 11:49:00 +00004647 }
4648}
4649
Steve Blocka7e24c12009-10-30 11:49:00 +00004650
4651#ifdef DEBUG
4652// Currently only used in an ASSERT.
4653static bool IsSpecialClassEscape(uc32 c) {
4654 switch (c) {
4655 case 'd': case 'D':
4656 case 's': case 'S':
4657 case 'w': case 'W':
4658 return true;
4659 default:
4660 return false;
4661 }
4662}
4663#endif
4664
4665
4666// In order to know whether an escape is a backreference or not we have to scan
4667// the entire regexp and find the number of capturing parentheses. However we
4668// don't want to scan the regexp twice unless it is necessary. This mini-parser
4669// is called when needed. It can see the difference between capturing and
4670// noncapturing parentheses and can skip character classes and backslash-escaped
4671// characters.
4672void RegExpParser::ScanForCaptures() {
4673 // Start with captures started previous to current position
4674 int capture_count = captures_started();
4675 // Add count of captures after this position.
4676 int n;
4677 while ((n = current()) != kEndMarker) {
4678 Advance();
4679 switch (n) {
4680 case '\\':
4681 Advance();
4682 break;
4683 case '[': {
4684 int c;
4685 while ((c = current()) != kEndMarker) {
4686 Advance();
4687 if (c == '\\') {
4688 Advance();
4689 } else {
4690 if (c == ']') break;
4691 }
4692 }
4693 break;
4694 }
4695 case '(':
4696 if (current() != '?') capture_count++;
4697 break;
4698 }
4699 }
4700 capture_count_ = capture_count;
4701 is_scanned_for_captures_ = true;
4702}
4703
4704
4705bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
4706 ASSERT_EQ('\\', current());
4707 ASSERT('1' <= Next() && Next() <= '9');
4708 // Try to parse a decimal literal that is no greater than the total number
4709 // of left capturing parentheses in the input.
4710 int start = position();
4711 int value = Next() - '0';
4712 Advance(2);
4713 while (true) {
4714 uc32 c = current();
4715 if (IsDecimalDigit(c)) {
4716 value = 10 * value + (c - '0');
4717 if (value > kMaxCaptures) {
4718 Reset(start);
4719 return false;
4720 }
4721 Advance();
4722 } else {
4723 break;
4724 }
4725 }
4726 if (value > captures_started()) {
4727 if (!is_scanned_for_captures_) {
4728 int saved_position = position();
4729 ScanForCaptures();
4730 Reset(saved_position);
4731 }
4732 if (value > capture_count_) {
4733 Reset(start);
4734 return false;
4735 }
4736 }
4737 *index_out = value;
4738 return true;
4739}
4740
4741
4742// QuantifierPrefix ::
4743// { DecimalDigits }
4744// { DecimalDigits , }
4745// { DecimalDigits , DecimalDigits }
4746//
4747// Returns true if parsing succeeds, and set the min_out and max_out
4748// values. Values are truncated to RegExpTree::kInfinity if they overflow.
4749bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
4750 ASSERT_EQ(current(), '{');
4751 int start = position();
4752 Advance();
4753 int min = 0;
4754 if (!IsDecimalDigit(current())) {
4755 Reset(start);
4756 return false;
4757 }
4758 while (IsDecimalDigit(current())) {
4759 int next = current() - '0';
4760 if (min > (RegExpTree::kInfinity - next) / 10) {
4761 // Overflow. Skip past remaining decimal digits and return -1.
4762 do {
4763 Advance();
4764 } while (IsDecimalDigit(current()));
4765 min = RegExpTree::kInfinity;
4766 break;
4767 }
4768 min = 10 * min + next;
4769 Advance();
4770 }
4771 int max = 0;
4772 if (current() == '}') {
4773 max = min;
4774 Advance();
4775 } else if (current() == ',') {
4776 Advance();
4777 if (current() == '}') {
4778 max = RegExpTree::kInfinity;
4779 Advance();
4780 } else {
4781 while (IsDecimalDigit(current())) {
4782 int next = current() - '0';
4783 if (max > (RegExpTree::kInfinity - next) / 10) {
4784 do {
4785 Advance();
4786 } while (IsDecimalDigit(current()));
4787 max = RegExpTree::kInfinity;
4788 break;
4789 }
4790 max = 10 * max + next;
4791 Advance();
4792 }
4793 if (current() != '}') {
4794 Reset(start);
4795 return false;
4796 }
4797 Advance();
4798 }
4799 } else {
4800 Reset(start);
4801 return false;
4802 }
4803 *min_out = min;
4804 *max_out = max;
4805 return true;
4806}
4807
4808
Steve Blocka7e24c12009-10-30 11:49:00 +00004809uc32 RegExpParser::ParseOctalLiteral() {
4810 ASSERT('0' <= current() && current() <= '7');
4811 // For compatibility with some other browsers (not all), we parse
4812 // up to three octal digits with a value below 256.
4813 uc32 value = current() - '0';
4814 Advance();
4815 if ('0' <= current() && current() <= '7') {
4816 value = value * 8 + current() - '0';
4817 Advance();
4818 if (value < 32 && '0' <= current() && current() <= '7') {
4819 value = value * 8 + current() - '0';
4820 Advance();
4821 }
4822 }
4823 return value;
4824}
4825
4826
4827bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
4828 int start = position();
4829 uc32 val = 0;
4830 bool done = false;
4831 for (int i = 0; !done; i++) {
4832 uc32 c = current();
4833 int d = HexValue(c);
4834 if (d < 0) {
4835 Reset(start);
4836 return false;
4837 }
4838 val = val * 16 + d;
4839 Advance();
4840 if (i == length - 1) {
4841 done = true;
4842 }
4843 }
4844 *value = val;
4845 return true;
4846}
4847
4848
4849uc32 RegExpParser::ParseClassCharacterEscape() {
4850 ASSERT(current() == '\\');
4851 ASSERT(has_next() && !IsSpecialClassEscape(Next()));
4852 Advance();
4853 switch (current()) {
4854 case 'b':
4855 Advance();
4856 return '\b';
4857 // ControlEscape :: one of
4858 // f n r t v
4859 case 'f':
4860 Advance();
4861 return '\f';
4862 case 'n':
4863 Advance();
4864 return '\n';
4865 case 'r':
4866 Advance();
4867 return '\r';
4868 case 't':
4869 Advance();
4870 return '\t';
4871 case 'v':
4872 Advance();
4873 return '\v';
Ben Murdoch086aeea2011-05-13 15:57:08 +01004874 case 'c': {
4875 uc32 controlLetter = Next();
4876 uc32 letter = controlLetter & ~('A' ^ 'a');
4877 // For compatibility with JSC, inside a character class
4878 // we also accept digits and underscore as control characters.
4879 if ((controlLetter >= '0' && controlLetter <= '9') ||
4880 controlLetter == '_' ||
4881 (letter >= 'A' && letter <= 'Z')) {
4882 Advance(2);
4883 // Control letters mapped to ASCII control characters in the range
4884 // 0x00-0x1f.
4885 return controlLetter & 0x1f;
4886 }
4887 // We match JSC in reading the backslash as a literal
4888 // character instead of as starting an escape.
4889 return '\\';
4890 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004891 case '0': case '1': case '2': case '3': case '4': case '5':
4892 case '6': case '7':
4893 // For compatibility, we interpret a decimal escape that isn't
4894 // a back reference (and therefore either \0 or not valid according
4895 // to the specification) as a 1..3 digit octal character code.
4896 return ParseOctalLiteral();
4897 case 'x': {
4898 Advance();
4899 uc32 value;
4900 if (ParseHexEscape(2, &value)) {
4901 return value;
4902 }
4903 // If \x is not followed by a two-digit hexadecimal, treat it
4904 // as an identity escape.
4905 return 'x';
4906 }
4907 case 'u': {
4908 Advance();
4909 uc32 value;
4910 if (ParseHexEscape(4, &value)) {
4911 return value;
4912 }
4913 // If \u is not followed by a four-digit hexadecimal, treat it
4914 // as an identity escape.
4915 return 'u';
4916 }
4917 default: {
4918 // Extended identity escape. We accept any character that hasn't
4919 // been matched by a more specific case, not just the subset required
4920 // by the ECMAScript specification.
4921 uc32 result = current();
4922 Advance();
4923 return result;
4924 }
4925 }
4926 return 0;
4927}
4928
4929
4930CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4931 ASSERT_EQ(0, *char_class);
4932 uc32 first = current();
4933 if (first == '\\') {
4934 switch (Next()) {
4935 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4936 *char_class = Next();
4937 Advance(2);
4938 return CharacterRange::Singleton(0); // Return dummy value.
4939 }
4940 case kEndMarker:
4941 return ReportError(CStrVector("\\ at end of pattern"));
4942 default:
4943 uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4944 return CharacterRange::Singleton(c);
4945 }
4946 } else {
4947 Advance();
4948 return CharacterRange::Singleton(first);
4949 }
4950}
4951
4952
Ben Murdochb0fe1622011-05-05 13:52:32 +01004953static const uc16 kNoCharClass = 0;
4954
4955// Adds range or pre-defined character class to character ranges.
4956// If char_class is not kInvalidClass, it's interpreted as a class
4957// escape (i.e., 's' means whitespace, from '\s').
4958static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
4959 uc16 char_class,
4960 CharacterRange range) {
4961 if (char_class != kNoCharClass) {
4962 CharacterRange::AddClassEscape(char_class, ranges);
4963 } else {
4964 ranges->Add(range);
4965 }
4966}
4967
4968
Steve Blocka7e24c12009-10-30 11:49:00 +00004969RegExpTree* RegExpParser::ParseCharacterClass() {
4970 static const char* kUnterminated = "Unterminated character class";
4971 static const char* kRangeOutOfOrder = "Range out of order in character class";
4972
4973 ASSERT_EQ(current(), '[');
4974 Advance();
4975 bool is_negated = false;
4976 if (current() == '^') {
4977 is_negated = true;
4978 Advance();
4979 }
Ben Murdoch257744e2011-11-30 15:57:28 +00004980 ZoneList<CharacterRange>* ranges = new(zone()) ZoneList<CharacterRange>(2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004981 while (has_more() && current() != ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004982 uc16 char_class = kNoCharClass;
Steve Blocka7e24c12009-10-30 11:49:00 +00004983 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004984 if (current() == '-') {
4985 Advance();
4986 if (current() == kEndMarker) {
4987 // If we reach the end we break out of the loop and let the
4988 // following code report an error.
4989 break;
4990 } else if (current() == ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004991 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004992 ranges->Add(CharacterRange::Singleton('-'));
4993 break;
4994 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01004995 uc16 char_class_2 = kNoCharClass;
4996 CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
4997 if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
4998 // Either end is an escaped character class. Treat the '-' verbatim.
4999 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00005000 ranges->Add(CharacterRange::Singleton('-'));
Ben Murdochb0fe1622011-05-05 13:52:32 +01005001 AddRangeOrEscape(ranges, char_class_2, next);
Steve Blocka7e24c12009-10-30 11:49:00 +00005002 continue;
5003 }
5004 if (first.from() > next.to()) {
5005 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
5006 }
5007 ranges->Add(CharacterRange::Range(first.from(), next.to()));
5008 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01005009 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00005010 }
5011 }
5012 if (!has_more()) {
5013 return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
5014 }
5015 Advance();
5016 if (ranges->length() == 0) {
5017 ranges->Add(CharacterRange::Everything());
5018 is_negated = !is_negated;
5019 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01005020 return new(zone()) RegExpCharacterClass(ranges, is_negated);
Steve Blocka7e24c12009-10-30 11:49:00 +00005021}
5022
5023
5024// ----------------------------------------------------------------------------
5025// The Parser interface.
5026
Steve Blocka7e24c12009-10-30 11:49:00 +00005027ParserMessage::~ParserMessage() {
5028 for (int i = 0; i < args().length(); i++)
5029 DeleteArray(args()[i]);
5030 DeleteArray(args().start());
5031}
5032
5033
5034ScriptDataImpl::~ScriptDataImpl() {
Iain Merrick9ac36c92010-09-13 15:29:50 +01005035 if (owns_store_) store_.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00005036}
5037
5038
5039int ScriptDataImpl::Length() {
Leon Clarkef7060e22010-06-03 12:02:55 +01005040 return store_.length() * sizeof(unsigned);
Steve Blocka7e24c12009-10-30 11:49:00 +00005041}
5042
5043
Leon Clarkef7060e22010-06-03 12:02:55 +01005044const char* ScriptDataImpl::Data() {
5045 return reinterpret_cast<const char*>(store_.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00005046}
5047
5048
Leon Clarkee46be812010-01-19 14:06:41 +00005049bool ScriptDataImpl::HasError() {
5050 return has_error();
5051}
5052
5053
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005054void ScriptDataImpl::Initialize() {
5055 // Prepares state for use.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005056 if (store_.length() >= PreparseDataConstants::kHeaderSize) {
5057 function_index_ = PreparseDataConstants::kHeaderSize;
5058 int symbol_data_offset = PreparseDataConstants::kHeaderSize
5059 + store_[PreparseDataConstants::kFunctionsSizeOffset];
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005060 if (store_.length() > symbol_data_offset) {
5061 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
5062 } else {
5063 // Partial preparse causes no symbol information.
5064 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5065 }
5066 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
5067 }
5068}
5069
5070
5071int ScriptDataImpl::ReadNumber(byte** source) {
5072 // Reads a number from symbol_data_ in base 128. The most significant
5073 // bit marks that there are more digits.
5074 // If the first byte is 0x80 (kNumberTerminator), it would normally
5075 // represent a leading zero. Since that is useless, and therefore won't
5076 // appear as the first digit of any actual value, it is used to
5077 // mark the end of the input stream.
5078 byte* data = *source;
5079 if (data >= symbol_data_end_) return -1;
5080 byte input = *data;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005081 if (input == PreparseDataConstants::kNumberTerminator) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005082 // End of stream marker.
5083 return -1;
5084 }
5085 int result = input & 0x7f;
5086 data++;
5087 while ((input & 0x80u) != 0) {
5088 if (data >= symbol_data_end_) return -1;
5089 input = *data;
5090 result = (result << 7) | (input & 0x7f);
5091 data++;
5092 }
5093 *source = data;
5094 return result;
5095}
5096
5097
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005098// Create a Scanner for the preparser to use as input, and preparse the source.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005099static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005100 bool allow_lazy,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005101 ParserRecorder* recorder,
5102 bool harmony_block_scoping) {
Steve Block44f0eee2011-05-26 01:26:41 +01005103 Isolate* isolate = Isolate::Current();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005104 JavaScriptScanner scanner(isolate->unicode_cache());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005105 scanner.SetHarmonyBlockScoping(harmony_block_scoping);
Steve Block9fac8402011-05-12 15:51:54 +01005106 scanner.Initialize(source);
Steve Block44f0eee2011-05-26 01:26:41 +01005107 intptr_t stack_limit = isolate->stack_guard()->real_climit();
Ben Murdochb0fe1622011-05-05 13:52:32 +01005108 if (!preparser::PreParser::PreParseProgram(&scanner,
5109 recorder,
5110 allow_lazy,
5111 stack_limit)) {
Steve Block44f0eee2011-05-26 01:26:41 +01005112 isolate->StackOverflow();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005113 return NULL;
5114 }
5115
Kristian Monsen80d68ea2010-09-08 11:05:35 +01005116 // Extract the accumulated data from the recorder as a single
5117 // contiguous vector that we are responsible for disposing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005118 Vector<unsigned> store = recorder->ExtractData();
Steve Blocka7e24c12009-10-30 11:49:00 +00005119 return new ScriptDataImpl(store);
5120}
5121
5122
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005123// Preparse, but only collect data that is immediately useful,
5124// even if the preparser data is only used once.
Ben Murdochb0fe1622011-05-05 13:52:32 +01005125ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005126 v8::Extension* extension,
5127 bool harmony_block_scoping) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005128 bool allow_lazy = FLAG_lazy && (extension == NULL);
5129 if (!allow_lazy) {
5130 // Partial preparsing is only about lazily compiled functions.
5131 // If we don't allow lazy compilation, the log data will be empty.
5132 return NULL;
5133 }
5134 PartialParserRecorder recorder;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005135 return DoPreParse(source, allow_lazy, &recorder, harmony_block_scoping);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08005136}
5137
5138
Ben Murdochb0fe1622011-05-05 13:52:32 +01005139ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005140 v8::Extension* extension,
5141 bool harmony_block_scoping) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005142 Handle<Script> no_script;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005143 bool allow_lazy = FLAG_lazy && (extension == NULL);
5144 CompleteParserRecorder recorder;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005145 return DoPreParse(source, allow_lazy, &recorder, harmony_block_scoping);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005146}
5147
5148
5149bool RegExpParser::ParseRegExp(FlatStringReader* input,
5150 bool multiline,
5151 RegExpCompileData* result) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005152 ASSERT(result != NULL);
5153 RegExpParser parser(input, &result->error, multiline);
5154 RegExpTree* tree = parser.ParsePattern();
5155 if (parser.failed()) {
5156 ASSERT(tree == NULL);
5157 ASSERT(!result->error.is_null());
5158 } else {
5159 ASSERT(tree != NULL);
5160 ASSERT(result->error.is_null());
5161 result->tree = tree;
5162 int capture_count = parser.captures_started();
5163 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
5164 result->contains_anchor = parser.contains_anchor();
5165 result->capture_count = capture_count;
5166 }
5167 return !parser.failed();
5168}
5169
5170
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005171bool ParserApi::Parse(CompilationInfo* info) {
Ben Murdochf87a2032010-10-22 12:50:53 +01005172 ASSERT(info->function() == NULL);
5173 FunctionLiteral* result = NULL;
5174 Handle<Script> script = info->script();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005175 bool harmony_block_scoping = !info->is_native() &&
5176 FLAG_harmony_block_scoping;
Ben Murdochf87a2032010-10-22 12:50:53 +01005177 if (info->is_lazy()) {
Ben Murdoch203a29f2011-10-20 14:36:23 +01005178 bool allow_natives_syntax =
5179 FLAG_allow_natives_syntax ||
5180 info->is_native();
5181 Parser parser(script, allow_natives_syntax, NULL, NULL);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005182 parser.SetHarmonyBlockScoping(harmony_block_scoping);
Steve Block44f0eee2011-05-26 01:26:41 +01005183 result = parser.ParseLazy(info);
Leon Clarke4515c472010-02-03 11:58:03 +00005184 } else {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005185 // Whether we allow %identifier(..) syntax.
Ben Murdochf87a2032010-10-22 12:50:53 +01005186 bool allow_natives_syntax =
Ben Murdoch203a29f2011-10-20 14:36:23 +01005187 info->is_native() || FLAG_allow_natives_syntax;
Ben Murdochf87a2032010-10-22 12:50:53 +01005188 ScriptDataImpl* pre_data = info->pre_parse_data();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005189 Parser parser(script,
5190 allow_natives_syntax,
5191 info->extension(),
5192 pre_data);
5193 parser.SetHarmonyBlockScoping(harmony_block_scoping);
Ben Murdochf87a2032010-10-22 12:50:53 +01005194 if (pre_data != NULL && pre_data->has_error()) {
5195 Scanner::Location loc = pre_data->MessageLocation();
5196 const char* message = pre_data->BuildMessage();
5197 Vector<const char*> args = pre_data->BuildArgs();
5198 parser.ReportMessageAt(loc, message, args);
5199 DeleteArray(message);
5200 for (int i = 0; i < args.length(); i++) {
5201 DeleteArray(args[i]);
5202 }
5203 DeleteArray(args.start());
Steve Block44f0eee2011-05-26 01:26:41 +01005204 ASSERT(info->isolate()->has_pending_exception());
Ben Murdochf87a2032010-10-22 12:50:53 +01005205 } else {
5206 Handle<String> source = Handle<String>(String::cast(script->source()));
Steve Block1e0659c2011-05-24 12:43:12 +01005207 result = parser.ParseProgram(source,
5208 info->is_global(),
5209 info->StrictMode());
Ben Murdochf87a2032010-10-22 12:50:53 +01005210 }
Leon Clarke4515c472010-02-03 11:58:03 +00005211 }
Ben Murdochf87a2032010-10-22 12:50:53 +01005212 info->SetFunction(result);
5213 return (result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00005214}
5215
Steve Blocka7e24c12009-10-30 11:49:00 +00005216} } // namespace v8::internal