blob: 5ea1c5e083ac44a15ea4ac100f1f6848d9d4fffd [file] [log] [blame]
Steve Block6ded16b2010-05-10 14:33:55 +01001// Copyright 2010 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"
31#include "ast.h"
32#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
Kristian Monsen25f61362010-05-21 11:50:48 +010044#include "ast-inl.h"
45#include "jump-target-inl.h"
46
Steve Blocka7e24c12009-10-30 11:49:00 +000047namespace v8 {
48namespace internal {
49
Steve Blocka7e24c12009-10-30 11:49:00 +000050// PositionStack is used for on-stack allocation of token positions for
51// new expressions. Please look at ParseNewExpression.
52
53class PositionStack {
54 public:
55 explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
56 ~PositionStack() { ASSERT(!*ok_ || is_empty()); }
57
58 class Element {
59 public:
60 Element(PositionStack* stack, int value) {
61 previous_ = stack->top();
62 value_ = value;
63 stack->set_top(this);
64 }
65
66 private:
67 Element* previous() { return previous_; }
68 int value() { return value_; }
69 friend class PositionStack;
70 Element* previous_;
71 int value_;
72 };
73
74 bool is_empty() { return top_ == NULL; }
75 int pop() {
76 ASSERT(!is_empty());
77 int result = top_->value();
78 top_ = top_->previous();
79 return result;
80 }
81
82 private:
83 Element* top() { return top_; }
84 void set_top(Element* value) { top_ = value; }
85 Element* top_;
86 bool* ok_;
87};
88
89
Steve Blocka7e24c12009-10-30 11:49:00 +000090RegExpBuilder::RegExpBuilder()
91 : pending_empty_(false),
92 characters_(NULL),
93 terms_(),
94 alternatives_()
95#ifdef DEBUG
96 , last_added_(ADD_NONE)
97#endif
98 {}
99
100
101void RegExpBuilder::FlushCharacters() {
102 pending_empty_ = false;
103 if (characters_ != NULL) {
104 RegExpTree* atom = new RegExpAtom(characters_->ToConstVector());
105 characters_ = NULL;
106 text_.Add(atom);
107 LAST(ADD_ATOM);
108 }
109}
110
111
112void RegExpBuilder::FlushText() {
113 FlushCharacters();
114 int num_text = text_.length();
115 if (num_text == 0) {
116 return;
117 } else if (num_text == 1) {
118 terms_.Add(text_.last());
119 } else {
120 RegExpText* text = new RegExpText();
121 for (int i = 0; i < num_text; i++)
122 text_.Get(i)->AppendToText(text);
123 terms_.Add(text);
124 }
125 text_.Clear();
126}
127
128
129void RegExpBuilder::AddCharacter(uc16 c) {
130 pending_empty_ = false;
131 if (characters_ == NULL) {
132 characters_ = new ZoneList<uc16>(4);
133 }
134 characters_->Add(c);
135 LAST(ADD_CHAR);
136}
137
138
139void RegExpBuilder::AddEmpty() {
140 pending_empty_ = true;
141}
142
143
144void RegExpBuilder::AddAtom(RegExpTree* term) {
145 if (term->IsEmpty()) {
146 AddEmpty();
147 return;
148 }
149 if (term->IsTextElement()) {
150 FlushCharacters();
151 text_.Add(term);
152 } else {
153 FlushText();
154 terms_.Add(term);
155 }
156 LAST(ADD_ATOM);
157}
158
159
160void RegExpBuilder::AddAssertion(RegExpTree* assert) {
161 FlushText();
162 terms_.Add(assert);
163 LAST(ADD_ASSERT);
164}
165
166
167void RegExpBuilder::NewAlternative() {
168 FlushTerms();
169}
170
171
172void RegExpBuilder::FlushTerms() {
173 FlushText();
174 int num_terms = terms_.length();
175 RegExpTree* alternative;
176 if (num_terms == 0) {
177 alternative = RegExpEmpty::GetInstance();
178 } else if (num_terms == 1) {
179 alternative = terms_.last();
180 } else {
181 alternative = new RegExpAlternative(terms_.GetList());
182 }
183 alternatives_.Add(alternative);
184 terms_.Clear();
185 LAST(ADD_NONE);
186}
187
188
189RegExpTree* RegExpBuilder::ToRegExp() {
190 FlushTerms();
191 int num_alternatives = alternatives_.length();
192 if (num_alternatives == 0) {
193 return RegExpEmpty::GetInstance();
194 }
195 if (num_alternatives == 1) {
196 return alternatives_.last();
197 }
198 return new RegExpDisjunction(alternatives_.GetList());
199}
200
201
Leon Clarkee46be812010-01-19 14:06:41 +0000202void RegExpBuilder::AddQuantifierToAtom(int min,
203 int max,
204 RegExpQuantifier::Type type) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000205 if (pending_empty_) {
206 pending_empty_ = false;
207 return;
208 }
209 RegExpTree* atom;
210 if (characters_ != NULL) {
211 ASSERT(last_added_ == ADD_CHAR);
212 // Last atom was character.
213 Vector<const uc16> char_vector = characters_->ToConstVector();
214 int num_chars = char_vector.length();
215 if (num_chars > 1) {
216 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
217 text_.Add(new RegExpAtom(prefix));
218 char_vector = char_vector.SubVector(num_chars - 1, num_chars);
219 }
220 characters_ = NULL;
221 atom = new RegExpAtom(char_vector);
222 FlushText();
223 } else if (text_.length() > 0) {
224 ASSERT(last_added_ == ADD_ATOM);
225 atom = text_.RemoveLast();
226 FlushText();
227 } else if (terms_.length() > 0) {
228 ASSERT(last_added_ == ADD_ATOM);
229 atom = terms_.RemoveLast();
230 if (atom->max_match() == 0) {
231 // Guaranteed to only match an empty string.
232 LAST(ADD_TERM);
233 if (min == 0) {
234 return;
235 }
236 terms_.Add(atom);
237 return;
238 }
239 } else {
240 // Only call immediately after adding an atom or character!
241 UNREACHABLE();
242 return;
243 }
Leon Clarkee46be812010-01-19 14:06:41 +0000244 terms_.Add(new RegExpQuantifier(min, max, type, atom));
Steve Blocka7e24c12009-10-30 11:49:00 +0000245 LAST(ADD_TERM);
246}
247
248
Steve Blocka7e24c12009-10-30 11:49:00 +0000249// A temporary scope stores information during parsing, just like
250// a plain scope. However, temporary scopes are not kept around
251// after parsing or referenced by syntax trees so they can be stack-
252// allocated and hence used by the pre-parser.
253class TemporaryScope BASE_EMBEDDED {
254 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800255 explicit TemporaryScope(TemporaryScope** variable);
Steve Blocka7e24c12009-10-30 11:49:00 +0000256 ~TemporaryScope();
257
258 int NextMaterializedLiteralIndex() {
259 int next_index =
260 materialized_literal_count_ + JSFunction::kLiteralsPrefixSize;
261 materialized_literal_count_++;
262 return next_index;
263 }
264 int materialized_literal_count() { return materialized_literal_count_; }
265
Steve Blocka7e24c12009-10-30 11:49:00 +0000266 void SetThisPropertyAssignmentInfo(
Steve Blocka7e24c12009-10-30 11:49:00 +0000267 bool only_simple_this_property_assignments,
268 Handle<FixedArray> this_property_assignments) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000269 only_simple_this_property_assignments_ =
270 only_simple_this_property_assignments;
271 this_property_assignments_ = this_property_assignments;
272 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000273 bool only_simple_this_property_assignments() {
274 return only_simple_this_property_assignments_;
275 }
276 Handle<FixedArray> this_property_assignments() {
277 return this_property_assignments_;
278 }
279
280 void AddProperty() { expected_property_count_++; }
281 int expected_property_count() { return expected_property_count_; }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100282
283 void AddLoop() { loop_count_++; }
284 bool ContainsLoops() const { return loop_count_ > 0; }
285
Steve Blocka7e24c12009-10-30 11:49:00 +0000286 private:
Steve Block3ce2e202009-11-05 08:53:23 +0000287 // Captures the number of literals that need materialization in the
288 // function. Includes regexp literals, and boilerplate for object
289 // and array literals.
Steve Blocka7e24c12009-10-30 11:49:00 +0000290 int materialized_literal_count_;
291
Steve Blocka7e24c12009-10-30 11:49:00 +0000292 // Properties count estimation.
293 int expected_property_count_;
294
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100295 // Keeps track of assignments to properties of this. Used for
296 // optimizing constructors.
Steve Blocka7e24c12009-10-30 11:49:00 +0000297 bool only_simple_this_property_assignments_;
298 Handle<FixedArray> this_property_assignments_;
299
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100300 // Captures the number of loops inside the scope.
301 int loop_count_;
302
Steve Blocka7e24c12009-10-30 11:49:00 +0000303 // Bookkeeping
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800304 TemporaryScope** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000305 TemporaryScope* parent_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000306};
307
308
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800309TemporaryScope::TemporaryScope(TemporaryScope** variable)
Steve Blocka7e24c12009-10-30 11:49:00 +0000310 : materialized_literal_count_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +0000311 expected_property_count_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +0000312 only_simple_this_property_assignments_(false),
313 this_property_assignments_(Factory::empty_fixed_array()),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100314 loop_count_(0),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800315 variable_(variable),
316 parent_(*variable) {
317 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000318}
319
320
321TemporaryScope::~TemporaryScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800322 *variable_ = parent_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000323}
324
325
Steve Block9fac8402011-05-12 15:51:54 +0100326Handle<String> Parser::LookupSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800327 // Length of symbol cache is the number of identified symbols.
328 // If we are larger than that, or negative, it's not a cached symbol.
329 // This might also happen if there is no preparser symbol data, even
330 // if there is some preparser data.
331 if (static_cast<unsigned>(symbol_id)
332 >= static_cast<unsigned>(symbol_cache_.length())) {
Steve Block9fac8402011-05-12 15:51:54 +0100333 if (scanner().is_literal_ascii()) {
334 return Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
335 } else {
336 return Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
337 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800338 }
Steve Block9fac8402011-05-12 15:51:54 +0100339 return LookupCachedSymbol(symbol_id);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800340}
341
342
Steve Block9fac8402011-05-12 15:51:54 +0100343Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800344 // Make sure the cache is large enough to hold the symbol identifier.
345 if (symbol_cache_.length() <= symbol_id) {
346 // Increase length to index + 1.
347 symbol_cache_.AddBlock(Handle<String>::null(),
348 symbol_id + 1 - symbol_cache_.length());
349 }
350 Handle<String> result = symbol_cache_.at(symbol_id);
351 if (result.is_null()) {
Steve Block9fac8402011-05-12 15:51:54 +0100352 if (scanner().is_literal_ascii()) {
353 result = Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
354 } else {
355 result = Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
356 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800357 symbol_cache_.at(symbol_id) = result;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100358 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000359 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800360 Counters::total_preparse_symbols_skipped.Increment();
361 return result;
362}
Steve Blocka7e24c12009-10-30 11:49:00 +0000363
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800364
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100365FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
366 // The current pre-data entry must be a FunctionEntry with the given
367 // start position.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100368 if ((function_index_ + FunctionEntry::kSize <= store_.length())
369 && (static_cast<int>(store_[function_index_]) == start)) {
370 int index = function_index_;
371 function_index_ += FunctionEntry::kSize;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100372 return FunctionEntry(store_.SubVector(index,
373 index + FunctionEntry::kSize));
Steve Blocka7e24c12009-10-30 11:49:00 +0000374 }
375 return FunctionEntry();
376}
377
378
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100379int ScriptDataImpl::GetSymbolIdentifier() {
380 return ReadNumber(&symbol_data_);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100381}
382
383
Iain Merrick9ac36c92010-09-13 15:29:50 +0100384bool ScriptDataImpl::SanityCheck() {
385 // Check that the header data is valid and doesn't specify
386 // point to positions outside the store.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800387 if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
388 if (magic() != PreparseDataConstants::kMagicNumber) return false;
389 if (version() != PreparseDataConstants::kCurrentVersion) return false;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100390 if (has_error()) {
391 // Extra sane sanity check for error message encoding.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800392 if (store_.length() <= PreparseDataConstants::kHeaderSize
393 + PreparseDataConstants::kMessageTextPos) {
394 return false;
395 }
396 if (Read(PreparseDataConstants::kMessageStartPos) >
397 Read(PreparseDataConstants::kMessageEndPos)) {
398 return false;
399 }
400 unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
401 int pos = PreparseDataConstants::kMessageTextPos;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100402 for (unsigned int i = 0; i <= arg_count; i++) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800403 if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
404 return false;
405 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100406 int length = static_cast<int>(Read(pos));
407 if (length < 0) return false;
408 pos += 1 + length;
409 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800410 if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
411 return false;
412 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100413 return true;
414 }
415 // Check that the space allocated for function entries is sane.
416 int functions_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800417 static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100418 if (functions_size < 0) return false;
419 if (functions_size % FunctionEntry::kSize != 0) return false;
420 // Check that the count of symbols is non-negative.
421 int symbol_count =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800422 static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100423 if (symbol_count < 0) return false;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100424 // Check that the total size has room for header and function entries.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100425 int minimum_size =
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800426 PreparseDataConstants::kHeaderSize + functions_size;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100427 if (store_.length() < minimum_size) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000428 return true;
429}
430
431
Steve Block59151502010-09-22 15:07:15 +0100432
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100433const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000434 int length = start[0];
435 char* result = NewArray<char>(length + 1);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100436 for (int i = 0; i < length; i++) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000437 result[i] = start[i + 1];
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100438 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000439 result[length] = '\0';
440 if (chars != NULL) *chars = length;
441 return result;
442}
443
Steve Blocka7e24c12009-10-30 11:49:00 +0000444Scanner::Location ScriptDataImpl::MessageLocation() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800445 int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
446 int end_pos = Read(PreparseDataConstants::kMessageEndPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000447 return Scanner::Location(beg_pos, end_pos);
448}
449
450
451const char* ScriptDataImpl::BuildMessage() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800452 unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100453 return ReadString(start, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000454}
455
456
457Vector<const char*> ScriptDataImpl::BuildArgs() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800458 int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000459 const char** array = NewArray<const char*>(arg_count);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100460 // Position after text found by skipping past length field and
461 // length field content words.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800462 int pos = PreparseDataConstants::kMessageTextPos + 1
463 + Read(PreparseDataConstants::kMessageTextPos);
Steve Blocka7e24c12009-10-30 11:49:00 +0000464 for (int i = 0; i < arg_count; i++) {
465 int count = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100466 array[i] = ReadString(ReadAddress(pos), &count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000467 pos += count + 1;
468 }
469 return Vector<const char*>(array, arg_count);
470}
471
472
473unsigned ScriptDataImpl::Read(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800474 return store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000475}
476
477
478unsigned* ScriptDataImpl::ReadAddress(int position) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800479 return &store_[PreparseDataConstants::kHeaderSize + position];
Steve Blocka7e24c12009-10-30 11:49:00 +0000480}
481
482
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800483Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000484 Scope* result = new Scope(parent, type);
485 result->Initialize(inside_with);
486 return result;
487}
488
Steve Blocka7e24c12009-10-30 11:49:00 +0000489// ----------------------------------------------------------------------------
490// Target is a support class to facilitate manipulation of the
491// Parser's target_stack_ (the stack of potential 'break' and
492// 'continue' statement targets). Upon construction, a new target is
493// added; it is removed upon destruction.
494
495class Target BASE_EMBEDDED {
496 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800497 Target(Target** variable, AstNode* node)
498 : variable_(variable), node_(node), previous_(*variable) {
499 *variable = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000500 }
501
502 ~Target() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800503 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000504 }
505
506 Target* previous() { return previous_; }
507 AstNode* node() { return node_; }
508
509 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800510 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000511 AstNode* node_;
512 Target* previous_;
513};
514
515
516class TargetScope BASE_EMBEDDED {
517 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800518 explicit TargetScope(Target** variable)
519 : variable_(variable), previous_(*variable) {
520 *variable = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000521 }
522
523 ~TargetScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800524 *variable_ = previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000525 }
526
527 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800528 Target** variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000529 Target* previous_;
530};
531
532
533// ----------------------------------------------------------------------------
534// LexicalScope is a support class to facilitate manipulation of the
535// Parser's scope stack. The constructor sets the parser's top scope
536// to the incoming scope, and the destructor resets it.
537
538class LexicalScope BASE_EMBEDDED {
539 public:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800540 LexicalScope(Scope** scope_variable,
541 int* with_nesting_level_variable,
542 Scope* scope)
543 : scope_variable_(scope_variable),
544 with_nesting_level_variable_(with_nesting_level_variable),
545 prev_scope_(*scope_variable),
546 prev_level_(*with_nesting_level_variable) {
547 *scope_variable = scope;
548 *with_nesting_level_variable = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000549 }
550
551 ~LexicalScope() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800552 (*scope_variable_)->Leave();
553 *scope_variable_ = prev_scope_;
554 *with_nesting_level_variable_ = prev_level_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000555 }
556
557 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800558 Scope** scope_variable_;
559 int* with_nesting_level_variable_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000560 Scope* prev_scope_;
561 int prev_level_;
562};
563
564
565// ----------------------------------------------------------------------------
566// The CHECK_OK macro is a convenient macro to enforce error
567// handling for functions that may fail (by returning !*ok).
568//
569// CAUTION: This macro appends extra statements after a call,
570// thus it must never be used where only a single statement
571// is correct (e.g. an if statement branch w/o braces)!
572
573#define CHECK_OK ok); \
574 if (!*ok) return NULL; \
575 ((void)0
576#define DUMMY ) // to make indentation work
577#undef DUMMY
578
579#define CHECK_FAILED /**/); \
580 if (failed_) return NULL; \
581 ((void)0
582#define DUMMY ) // to make indentation work
583#undef DUMMY
584
585// ----------------------------------------------------------------------------
586// Implementation of Parser
587
588Parser::Parser(Handle<Script> script,
589 bool allow_natives_syntax,
590 v8::Extension* extension,
Steve Blocka7e24c12009-10-30 11:49:00 +0000591 ScriptDataImpl* pre_data)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800592 : symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
593 script_(script),
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100594 scanner_(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000595 top_scope_(NULL),
596 with_nesting_level_(0),
597 temp_scope_(NULL),
598 target_stack_(NULL),
599 allow_natives_syntax_(allow_natives_syntax),
600 extension_(extension),
Steve Block6ded16b2010-05-10 14:33:55 +0100601 pre_data_(pre_data),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100602 fni_(NULL),
603 stack_overflow_(false) {
604 AstNode::ResetIds();
Steve Blocka7e24c12009-10-30 11:49:00 +0000605}
606
607
Steve Blocka7e24c12009-10-30 11:49:00 +0000608FunctionLiteral* Parser::ParseProgram(Handle<String> source,
Steve Blocka7e24c12009-10-30 11:49:00 +0000609 bool in_global_context) {
610 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
611
612 HistogramTimerScope timer(&Counters::parse);
613 Counters::total_parse_size.Increment(source->length());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100614 fni_ = new FuncNameInferrer();
Steve Blocka7e24c12009-10-30 11:49:00 +0000615
616 // Initialize parser state.
Steve Block6ded16b2010-05-10 14:33:55 +0100617 source->TryFlatten();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100618 if (source->IsExternalTwoByteString()) {
619 // Notice that the stream is destroyed at the end of the branch block.
620 // The last line of the blocks can't be moved outside, even though they're
621 // identical calls.
622 ExternalTwoByteStringUC16CharacterStream stream(
623 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100624 scanner_.Initialize(&stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100625 return DoParseProgram(source, in_global_context, &zone_scope);
626 } else {
627 GenericStringUC16CharacterStream stream(source, 0, source->length());
Steve Block9fac8402011-05-12 15:51:54 +0100628 scanner_.Initialize(&stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100629 return DoParseProgram(source, in_global_context, &zone_scope);
630 }
631}
632
633
634FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
635 bool in_global_context,
636 ZoneScope* zone_scope) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000637 ASSERT(target_stack_ == NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100638 if (pre_data_ != NULL) pre_data_->Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000639
640 // Compute the parsing mode.
641 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
642 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
643
644 Scope::Type type =
645 in_global_context
646 ? Scope::GLOBAL_SCOPE
647 : Scope::EVAL_SCOPE;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800648 Handle<String> no_name = Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000649
650 FunctionLiteral* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800651 { Scope* scope = NewScope(top_scope_, type, inside_with());
652 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
653 scope);
654 TemporaryScope temp_scope(&this->temp_scope_);
655 ZoneList<Statement*>* body = new ZoneList<Statement*>(16);
Steve Blocka7e24c12009-10-30 11:49:00 +0000656 bool ok = true;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800657 ParseSourceElements(body, Token::EOS, &ok);
Steve Blocka7e24c12009-10-30 11:49:00 +0000658 if (ok) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800659 result = new FunctionLiteral(
Steve Blocka7e24c12009-10-30 11:49:00 +0000660 no_name,
661 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800662 body,
Steve Blocka7e24c12009-10-30 11:49:00 +0000663 temp_scope.materialized_literal_count(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000664 temp_scope.expected_property_count(),
Steve Blocka7e24c12009-10-30 11:49:00 +0000665 temp_scope.only_simple_this_property_assignments(),
666 temp_scope.this_property_assignments(),
667 0,
668 0,
669 source->length(),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100670 false,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800671 temp_scope.ContainsLoops());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100672 } else if (stack_overflow_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000673 Top::StackOverflow();
674 }
675 }
676
677 // Make sure the target stack is empty.
678 ASSERT(target_stack_ == NULL);
679
680 // If there was a syntax error we have to get rid of the AST
681 // and it is not safe to do so before the scope has been deleted.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100682 if (result == NULL) zone_scope->DeleteOnExit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000683 return result;
684}
685
Ben Murdochf87a2032010-10-22 12:50:53 +0100686FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000687 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
688 HistogramTimerScope timer(&Counters::parse_lazy);
Ben Murdochf87a2032010-10-22 12:50:53 +0100689 Handle<String> source(String::cast(script_->source()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000690 Counters::total_parse_size.Increment(source->length());
Steve Blocka7e24c12009-10-30 11:49:00 +0000691
Ben Murdochb0fe1622011-05-05 13:52:32 +0100692 // Initialize parser state.
693 source->TryFlatten();
694 if (source->IsExternalTwoByteString()) {
695 ExternalTwoByteStringUC16CharacterStream stream(
696 Handle<ExternalTwoByteString>::cast(source),
697 info->start_position(),
698 info->end_position());
699 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
700 return result;
701 } else {
702 GenericStringUC16CharacterStream stream(source,
703 info->start_position(),
704 info->end_position());
705 FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
706 return result;
707 }
708}
709
710
711FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
712 UC16CharacterStream* source,
713 ZoneScope* zone_scope) {
Steve Block9fac8402011-05-12 15:51:54 +0100714 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100715 ASSERT(target_stack_ == NULL);
716
Ben Murdochf87a2032010-10-22 12:50:53 +0100717 Handle<String> name(String::cast(info->name()));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100718 fni_ = new FuncNameInferrer();
719 fni_->PushEnclosingName(name);
720
Steve Blocka7e24c12009-10-30 11:49:00 +0000721 mode_ = PARSE_EAGERLY;
722
723 // Place holder for the result.
724 FunctionLiteral* result = NULL;
725
726 {
727 // Parse the function literal.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800728 Handle<String> no_name = Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +0000729 Scope* scope =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800730 NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
731 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
732 scope);
733 TemporaryScope temp_scope(&this->temp_scope_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000734
Ben Murdochf87a2032010-10-22 12:50:53 +0100735 FunctionLiteralType type =
736 info->is_expression() ? EXPRESSION : DECLARATION;
Steve Blocka7e24c12009-10-30 11:49:00 +0000737 bool ok = true;
738 result = ParseFunctionLiteral(name, RelocInfo::kNoPosition, type, &ok);
739 // Make sure the results agree.
740 ASSERT(ok == (result != NULL));
741 // The only errors should be stack overflows.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100742 ASSERT(ok || stack_overflow_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000743 }
744
745 // Make sure the target stack is empty.
746 ASSERT(target_stack_ == NULL);
747
748 // If there was a stack overflow we have to get rid of AST and it is
749 // not safe to do before scope has been deleted.
750 if (result == NULL) {
751 Top::StackOverflow();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100752 zone_scope->DeleteOnExit();
753 } else {
754 Handle<String> inferred_name(info->inferred_name());
755 result->set_inferred_name(inferred_name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000756 }
757 return result;
758}
759
Ben Murdochf87a2032010-10-22 12:50:53 +0100760
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800761Handle<String> Parser::GetSymbol(bool* ok) {
762 int symbol_id = -1;
763 if (pre_data() != NULL) {
764 symbol_id = pre_data()->GetSymbolIdentifier();
Leon Clarke4515c472010-02-03 11:58:03 +0000765 }
Steve Block9fac8402011-05-12 15:51:54 +0100766 return LookupSymbol(symbol_id);
Leon Clarke4515c472010-02-03 11:58:03 +0000767}
Steve Blocka7e24c12009-10-30 11:49:00 +0000768
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800769
Steve Blocka7e24c12009-10-30 11:49:00 +0000770void Parser::ReportMessage(const char* type, Vector<const char*> args) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100771 Scanner::Location source_location = scanner().location();
Steve Blocka7e24c12009-10-30 11:49:00 +0000772 ReportMessageAt(source_location, type, args);
773}
774
775
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800776void Parser::ReportMessageAt(Scanner::Location source_location,
777 const char* type,
778 Vector<const char*> args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000779 MessageLocation location(script_,
780 source_location.beg_pos, source_location.end_pos);
781 Handle<JSArray> array = Factory::NewJSArray(args.length());
782 for (int i = 0; i < args.length(); i++) {
783 SetElement(array, i, Factory::NewStringFromUtf8(CStrVector(args[i])));
784 }
785 Handle<Object> result = Factory::NewSyntaxError(type, array);
786 Top::Throw(*result, &location);
787}
788
789
Steve Blocka7e24c12009-10-30 11:49:00 +0000790// Base class containing common code for the different finder classes used by
791// the parser.
792class ParserFinder {
793 protected:
794 ParserFinder() {}
795 static Assignment* AsAssignment(Statement* stat) {
796 if (stat == NULL) return NULL;
797 ExpressionStatement* exp_stat = stat->AsExpressionStatement();
798 if (exp_stat == NULL) return NULL;
799 return exp_stat->expression()->AsAssignment();
800 }
801};
802
803
804// An InitializationBlockFinder finds and marks sequences of statements of the
Steve Blockd0582a62009-12-15 09:54:21 +0000805// form expr.a = ...; expr.b = ...; etc.
Steve Blocka7e24c12009-10-30 11:49:00 +0000806class InitializationBlockFinder : public ParserFinder {
807 public:
808 InitializationBlockFinder()
809 : first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {}
810
811 ~InitializationBlockFinder() {
812 if (InBlock()) EndBlock();
813 }
814
815 void Update(Statement* stat) {
816 Assignment* assignment = AsAssignment(stat);
817 if (InBlock()) {
818 if (BlockContinues(assignment)) {
819 UpdateBlock(assignment);
820 } else {
821 EndBlock();
822 }
823 }
824 if (!InBlock() && (assignment != NULL) &&
825 (assignment->op() == Token::ASSIGN)) {
826 StartBlock(assignment);
827 }
828 }
829
830 private:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800831 // The minimum number of contiguous assignment that will
832 // be treated as an initialization block. Benchmarks show that
833 // the overhead exceeds the savings below this limit.
834 static const int kMinInitializationBlock = 3;
835
Steve Blocka7e24c12009-10-30 11:49:00 +0000836 // Returns true if the expressions appear to denote the same object.
837 // In the context of initialization blocks, we only consider expressions
Steve Blockd0582a62009-12-15 09:54:21 +0000838 // of the form 'expr.x' or expr["x"].
Steve Blocka7e24c12009-10-30 11:49:00 +0000839 static bool SameObject(Expression* e1, Expression* e2) {
840 VariableProxy* v1 = e1->AsVariableProxy();
841 VariableProxy* v2 = e2->AsVariableProxy();
842 if (v1 != NULL && v2 != NULL) {
843 return v1->name()->Equals(*v2->name());
844 }
845 Property* p1 = e1->AsProperty();
846 Property* p2 = e2->AsProperty();
847 if ((p1 == NULL) || (p2 == NULL)) return false;
848 Literal* key1 = p1->key()->AsLiteral();
849 Literal* key2 = p2->key()->AsLiteral();
850 if ((key1 == NULL) || (key2 == NULL)) return false;
851 if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
852 return false;
853 }
854 String* name1 = String::cast(*key1->handle());
855 String* name2 = String::cast(*key2->handle());
856 if (!name1->Equals(name2)) return false;
857 return SameObject(p1->obj(), p2->obj());
858 }
859
860 // Returns true if the expressions appear to denote different properties
861 // of the same object.
862 static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
863 Property* p1 = e1->AsProperty();
864 Property* p2 = e2->AsProperty();
865 if ((p1 == NULL) || (p2 == NULL)) return false;
866 return SameObject(p1->obj(), p2->obj());
867 }
868
869 bool BlockContinues(Assignment* assignment) {
870 if ((assignment == NULL) || (first_in_block_ == NULL)) return false;
871 if (assignment->op() != Token::ASSIGN) return false;
872 return PropertyOfSameObject(first_in_block_->target(),
873 assignment->target());
874 }
875
876 void StartBlock(Assignment* assignment) {
877 first_in_block_ = assignment;
878 last_in_block_ = assignment;
879 block_size_ = 1;
880 }
881
882 void UpdateBlock(Assignment* assignment) {
883 last_in_block_ = assignment;
884 ++block_size_;
885 }
886
887 void EndBlock() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800888 if (block_size_ >= kMinInitializationBlock) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000889 first_in_block_->mark_block_start();
890 last_in_block_->mark_block_end();
891 }
892 last_in_block_ = first_in_block_ = NULL;
893 block_size_ = 0;
894 }
895
896 bool InBlock() { return first_in_block_ != NULL; }
897
898 Assignment* first_in_block_;
899 Assignment* last_in_block_;
900 int block_size_;
901
902 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
903};
904
905
906// A ThisNamedPropertyAssigmentFinder finds and marks statements of the form
907// this.x = ...;, where x is a named property. It also determines whether a
908// function contains only assignments of this type.
909class ThisNamedPropertyAssigmentFinder : public ParserFinder {
910 public:
911 ThisNamedPropertyAssigmentFinder()
Steve Blockd0582a62009-12-15 09:54:21 +0000912 : only_simple_this_property_assignments_(true),
Steve Blocka7e24c12009-10-30 11:49:00 +0000913 names_(NULL),
914 assigned_arguments_(NULL),
915 assigned_constants_(NULL) {}
916
917 void Update(Scope* scope, Statement* stat) {
Steve Blockd0582a62009-12-15 09:54:21 +0000918 // Bail out if function already has property assignment that are
919 // not simple this property assignments.
920 if (!only_simple_this_property_assignments_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000921 return;
922 }
923
924 // Check whether this statement is of the form this.x = ...;
925 Assignment* assignment = AsAssignment(stat);
926 if (IsThisPropertyAssignment(assignment)) {
927 HandleThisPropertyAssignment(scope, assignment);
928 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +0000929 only_simple_this_property_assignments_ = false;
930 }
931 }
932
Steve Blocka7e24c12009-10-30 11:49:00 +0000933 // Returns whether only statements of the form this.x = y; where y is either a
934 // constant or a function argument was encountered.
935 bool only_simple_this_property_assignments() {
936 return only_simple_this_property_assignments_;
937 }
938
939 // Returns a fixed array containing three elements for each assignment of the
940 // form this.x = y;
941 Handle<FixedArray> GetThisPropertyAssignments() {
942 if (names_ == NULL) {
943 return Factory::empty_fixed_array();
944 }
945 ASSERT(names_ != NULL);
946 ASSERT(assigned_arguments_ != NULL);
947 ASSERT_EQ(names_->length(), assigned_arguments_->length());
948 ASSERT_EQ(names_->length(), assigned_constants_->length());
949 Handle<FixedArray> assignments =
950 Factory::NewFixedArray(names_->length() * 3);
951 for (int i = 0; i < names_->length(); i++) {
952 assignments->set(i * 3, *names_->at(i));
953 assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i)));
954 assignments->set(i * 3 + 2, *assigned_constants_->at(i));
955 }
956 return assignments;
957 }
958
959 private:
960 bool IsThisPropertyAssignment(Assignment* assignment) {
961 if (assignment != NULL) {
962 Property* property = assignment->target()->AsProperty();
963 return assignment->op() == Token::ASSIGN
964 && property != NULL
965 && property->obj()->AsVariableProxy() != NULL
966 && property->obj()->AsVariableProxy()->is_this();
967 }
968 return false;
969 }
970
971 void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
Steve Block6ded16b2010-05-10 14:33:55 +0100972 // Check that the property assigned to is a named property, which is not
973 // __proto__.
Steve Blocka7e24c12009-10-30 11:49:00 +0000974 Property* property = assignment->target()->AsProperty();
975 ASSERT(property != NULL);
976 Literal* literal = property->key()->AsLiteral();
977 uint32_t dummy;
978 if (literal != NULL &&
979 literal->handle()->IsString() &&
Steve Block6ded16b2010-05-10 14:33:55 +0100980 !String::cast(*(literal->handle()))->Equals(Heap::Proto_symbol()) &&
Steve Blocka7e24c12009-10-30 11:49:00 +0000981 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
982 Handle<String> key = Handle<String>::cast(literal->handle());
983
984 // Check whether the value assigned is either a constant or matches the
985 // name of one of the arguments to the function.
986 if (assignment->value()->AsLiteral() != NULL) {
987 // Constant assigned.
988 Literal* literal = assignment->value()->AsLiteral();
989 AssignmentFromConstant(key, literal->handle());
Steve Blockd0582a62009-12-15 09:54:21 +0000990 return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000991 } else if (assignment->value()->AsVariableProxy() != NULL) {
992 // Variable assigned.
993 Handle<String> name =
994 assignment->value()->AsVariableProxy()->name();
995 // Check whether the variable assigned matches an argument name.
Steve Blocka7e24c12009-10-30 11:49:00 +0000996 for (int i = 0; i < scope->num_parameters(); i++) {
997 if (*scope->parameter(i)->name() == *name) {
998 // Assigned from function argument.
Steve Blockd0582a62009-12-15 09:54:21 +0000999 AssignmentFromParameter(key, i);
1000 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001001 }
1002 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001003 }
1004 }
Steve Blockd0582a62009-12-15 09:54:21 +00001005 // It is not a simple "this.x = value;" assignment with a constant
1006 // or parameter value.
1007 AssignmentFromSomethingElse();
Steve Blocka7e24c12009-10-30 11:49:00 +00001008 }
1009
1010 void AssignmentFromParameter(Handle<String> name, int index) {
1011 EnsureAllocation();
1012 names_->Add(name);
1013 assigned_arguments_->Add(index);
1014 assigned_constants_->Add(Factory::undefined_value());
1015 }
1016
1017 void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
1018 EnsureAllocation();
1019 names_->Add(name);
1020 assigned_arguments_->Add(-1);
1021 assigned_constants_->Add(value);
1022 }
1023
Steve Blockd0582a62009-12-15 09:54:21 +00001024 void AssignmentFromSomethingElse() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001025 // The this assignment is not a simple one.
1026 only_simple_this_property_assignments_ = false;
1027 }
1028
1029 void EnsureAllocation() {
1030 if (names_ == NULL) {
1031 ASSERT(assigned_arguments_ == NULL);
1032 ASSERT(assigned_constants_ == NULL);
1033 names_ = new ZoneStringList(4);
1034 assigned_arguments_ = new ZoneList<int>(4);
1035 assigned_constants_ = new ZoneObjectList(4);
1036 }
1037 }
1038
Steve Blocka7e24c12009-10-30 11:49:00 +00001039 bool only_simple_this_property_assignments_;
1040 ZoneStringList* names_;
1041 ZoneList<int>* assigned_arguments_;
1042 ZoneObjectList* assigned_constants_;
1043};
1044
1045
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001046void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
Steve Blocka7e24c12009-10-30 11:49:00 +00001047 int end_token,
1048 bool* ok) {
1049 // SourceElements ::
1050 // (Statement)* <end_token>
1051
1052 // Allocate a target stack to use for this set of source
1053 // elements. This way, all scripts and functions get their own
1054 // target stack thus avoiding illegal breaks and continues across
1055 // functions.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001056 TargetScope scope(&this->target_stack_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001057
1058 ASSERT(processor != NULL);
1059 InitializationBlockFinder block_finder;
1060 ThisNamedPropertyAssigmentFinder this_property_assignment_finder;
1061 while (peek() != end_token) {
1062 Statement* stat = ParseStatement(NULL, CHECK_OK);
1063 if (stat == NULL || stat->IsEmpty()) continue;
1064 // We find and mark the initialization blocks on top level code only.
1065 // This is because the optimization prevents reuse of the map transitions,
1066 // so it should be used only for code that will only be run once.
1067 if (top_scope_->is_global_scope()) {
1068 block_finder.Update(stat);
1069 }
1070 // Find and mark all assignments to named properties in this (this.x =)
1071 if (top_scope_->is_function_scope()) {
1072 this_property_assignment_finder.Update(top_scope_, stat);
1073 }
1074 processor->Add(stat);
1075 }
1076
1077 // Propagate the collected information on this property assignments.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001078 if (top_scope_->is_function_scope()) {
Steve Blockd0582a62009-12-15 09:54:21 +00001079 bool only_simple_this_property_assignments =
Andrei Popescu402d9372010-02-26 13:31:12 +00001080 this_property_assignment_finder.only_simple_this_property_assignments()
1081 && top_scope_->declarations()->length() == 0;
Steve Blockd0582a62009-12-15 09:54:21 +00001082 if (only_simple_this_property_assignments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001083 temp_scope_->SetThisPropertyAssignmentInfo(
Steve Blockd0582a62009-12-15 09:54:21 +00001084 only_simple_this_property_assignments,
Steve Blocka7e24c12009-10-30 11:49:00 +00001085 this_property_assignment_finder.GetThisPropertyAssignments());
1086 }
1087 }
1088 return 0;
1089}
1090
1091
1092Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1093 // Statement ::
1094 // Block
1095 // VariableStatement
1096 // EmptyStatement
1097 // ExpressionStatement
1098 // IfStatement
1099 // IterationStatement
1100 // ContinueStatement
1101 // BreakStatement
1102 // ReturnStatement
1103 // WithStatement
1104 // LabelledStatement
1105 // SwitchStatement
1106 // ThrowStatement
1107 // TryStatement
1108 // DebuggerStatement
1109
1110 // Note: Since labels can only be used by 'break' and 'continue'
1111 // statements, which themselves are only valid within blocks,
1112 // iterations or 'switch' statements (i.e., BreakableStatements),
1113 // labels can be simply ignored in all other cases; except for
1114 // trivial labeled break statements 'label: break label' which is
1115 // parsed into an empty statement.
1116
1117 // Keep the source position of the statement
1118 int statement_pos = scanner().peek_location().beg_pos;
1119 Statement* stmt = NULL;
1120 switch (peek()) {
1121 case Token::LBRACE:
1122 return ParseBlock(labels, ok);
1123
1124 case Token::CONST: // fall through
1125 case Token::VAR:
1126 stmt = ParseVariableStatement(ok);
1127 break;
1128
1129 case Token::SEMICOLON:
1130 Next();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001131 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001132
1133 case Token::IF:
1134 stmt = ParseIfStatement(labels, ok);
1135 break;
1136
1137 case Token::DO:
Steve Block3ce2e202009-11-05 08:53:23 +00001138 stmt = ParseDoWhileStatement(labels, ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00001139 break;
1140
1141 case Token::WHILE:
1142 stmt = ParseWhileStatement(labels, ok);
1143 break;
1144
1145 case Token::FOR:
1146 stmt = ParseForStatement(labels, ok);
1147 break;
1148
1149 case Token::CONTINUE:
1150 stmt = ParseContinueStatement(ok);
1151 break;
1152
1153 case Token::BREAK:
1154 stmt = ParseBreakStatement(labels, ok);
1155 break;
1156
1157 case Token::RETURN:
1158 stmt = ParseReturnStatement(ok);
1159 break;
1160
1161 case Token::WITH:
1162 stmt = ParseWithStatement(labels, ok);
1163 break;
1164
1165 case Token::SWITCH:
1166 stmt = ParseSwitchStatement(labels, ok);
1167 break;
1168
1169 case Token::THROW:
1170 stmt = ParseThrowStatement(ok);
1171 break;
1172
1173 case Token::TRY: {
1174 // NOTE: It is somewhat complicated to have labels on
1175 // try-statements. When breaking out of a try-finally statement,
1176 // one must take great care not to treat it as a
1177 // fall-through. It is much easier just to wrap the entire
1178 // try-statement in a statement block and put the labels there
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001179 Block* result = new Block(labels, 1, false);
1180 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001181 TryStatement* statement = ParseTryStatement(CHECK_OK);
1182 if (statement) {
1183 statement->set_statement_pos(statement_pos);
1184 }
1185 if (result) result->AddStatement(statement);
1186 return result;
1187 }
1188
1189 case Token::FUNCTION:
1190 return ParseFunctionDeclaration(ok);
1191
1192 case Token::NATIVE:
1193 return ParseNativeDeclaration(ok);
1194
1195 case Token::DEBUGGER:
1196 stmt = ParseDebuggerStatement(ok);
1197 break;
1198
1199 default:
1200 stmt = ParseExpressionOrLabelledStatement(labels, ok);
1201 }
1202
1203 // Store the source position of the statement
1204 if (stmt != NULL) stmt->set_statement_pos(statement_pos);
1205 return stmt;
1206}
1207
1208
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001209VariableProxy* Parser::Declare(Handle<String> name,
1210 Variable::Mode mode,
1211 FunctionLiteral* fun,
1212 bool resolve,
1213 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001214 Variable* var = NULL;
1215 // If we are inside a function, a declaration of a variable
1216 // is a truly local variable, and the scope of the variable
1217 // is always the function scope.
1218
1219 // If a function scope exists, then we can statically declare this
1220 // variable and also set its mode. In any case, a Declaration node
1221 // will be added to the scope so that the declaration can be added
1222 // to the corresponding activation frame at runtime if necessary.
1223 // For instance declarations inside an eval scope need to be added
1224 // to the calling function context.
1225 if (top_scope_->is_function_scope()) {
1226 // Declare the variable in the function scope.
1227 var = top_scope_->LocalLookup(name);
1228 if (var == NULL) {
1229 // Declare the name.
1230 var = top_scope_->DeclareLocal(name, mode);
1231 } else {
1232 // The name was declared before; check for conflicting
1233 // re-declarations. If the previous declaration was a const or the
1234 // current declaration is a const then we have a conflict. There is
1235 // similar code in runtime.cc in the Declare functions.
1236 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) {
1237 // We only have vars and consts in declarations.
1238 ASSERT(var->mode() == Variable::VAR ||
1239 var->mode() == Variable::CONST);
1240 const char* type = (var->mode() == Variable::VAR) ? "var" : "const";
1241 Handle<String> type_string =
1242 Factory::NewStringFromUtf8(CStrVector(type), TENURED);
1243 Expression* expression =
1244 NewThrowTypeError(Factory::redeclaration_symbol(),
1245 type_string, name);
1246 top_scope_->SetIllegalRedeclaration(expression);
1247 }
1248 }
1249 }
1250
1251 // We add a declaration node for every declaration. The compiler
1252 // will only generate code if necessary. In particular, declarations
1253 // for inner local variables that do not represent functions won't
1254 // result in any generated code.
1255 //
1256 // Note that we always add an unresolved proxy even if it's not
1257 // used, simply because we don't know in this method (w/o extra
1258 // parameters) if the proxy is needed or not. The proxy will be
1259 // bound during variable resolution time unless it was pre-bound
1260 // below.
1261 //
1262 // WARNING: This will lead to multiple declaration nodes for the
1263 // same variable if it is declared several times. This is not a
1264 // semantic issue as long as we keep the source order, but it may be
1265 // a performance issue since it may lead to repeated
1266 // Runtime::DeclareContextSlot() calls.
1267 VariableProxy* proxy = top_scope_->NewUnresolved(name, inside_with());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001268 top_scope_->AddDeclaration(new Declaration(proxy, mode, fun));
Steve Blocka7e24c12009-10-30 11:49:00 +00001269
1270 // For global const variables we bind the proxy to a variable.
1271 if (mode == Variable::CONST && top_scope_->is_global_scope()) {
1272 ASSERT(resolve); // should be set by all callers
1273 Variable::Kind kind = Variable::NORMAL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001274 var = new Variable(top_scope_, name, Variable::CONST, true, kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001275 }
1276
1277 // If requested and we have a local variable, bind the proxy to the variable
1278 // at parse-time. This is used for functions (and consts) declared inside
1279 // statements: the corresponding function (or const) variable must be in the
1280 // function scope and not a statement-local scope, e.g. as provided with a
1281 // 'with' statement:
1282 //
1283 // with (obj) {
1284 // function f() {}
1285 // }
1286 //
1287 // which is translated into:
1288 //
1289 // with (obj) {
1290 // // in this case this is not: 'var f; f = function () {};'
1291 // var f = function () {};
1292 // }
1293 //
1294 // Note that if 'f' is accessed from inside the 'with' statement, it
1295 // will be allocated in the context (because we must be able to look
1296 // it up dynamically) but it will also be accessed statically, i.e.,
1297 // with a context slot index and a context chain length for this
1298 // initialization code. Thus, inside the 'with' statement, we need
1299 // both access to the static and the dynamic context chain; the
1300 // runtime needs to provide both.
1301 if (resolve && var != NULL) proxy->BindTo(var);
1302
1303 return proxy;
1304}
1305
1306
1307// Language extension which is only enabled for source files loaded
1308// through the API's extension mechanism. A native function
1309// declaration is resolved by looking up the function through a
1310// callback provided by the extension.
1311Statement* Parser::ParseNativeDeclaration(bool* ok) {
1312 if (extension_ == NULL) {
1313 ReportUnexpectedToken(Token::NATIVE);
1314 *ok = false;
1315 return NULL;
1316 }
1317
1318 Expect(Token::NATIVE, CHECK_OK);
1319 Expect(Token::FUNCTION, CHECK_OK);
1320 Handle<String> name = ParseIdentifier(CHECK_OK);
1321 Expect(Token::LPAREN, CHECK_OK);
1322 bool done = (peek() == Token::RPAREN);
1323 while (!done) {
1324 ParseIdentifier(CHECK_OK);
1325 done = (peek() == Token::RPAREN);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001326 if (!done) {
1327 Expect(Token::COMMA, CHECK_OK);
1328 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001329 }
1330 Expect(Token::RPAREN, CHECK_OK);
1331 Expect(Token::SEMICOLON, CHECK_OK);
1332
Steve Blocka7e24c12009-10-30 11:49:00 +00001333 // Make sure that the function containing the native declaration
1334 // isn't lazily compiled. The extension structures are only
1335 // accessible while parsing the first time not when reparsing
1336 // because of lazy compilation.
1337 top_scope_->ForceEagerCompilation();
1338
1339 // Compute the function template for the native function.
1340 v8::Handle<v8::FunctionTemplate> fun_template =
1341 extension_->GetNativeFunction(v8::Utils::ToLocal(name));
1342 ASSERT(!fun_template.IsEmpty());
1343
Steve Block6ded16b2010-05-10 14:33:55 +01001344 // Instantiate the function and create a shared function info from it.
Steve Blocka7e24c12009-10-30 11:49:00 +00001345 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1346 const int literals = fun->NumberOfLiterals();
1347 Handle<Code> code = Handle<Code>(fun->shared()->code());
Leon Clarkee46be812010-01-19 14:06:41 +00001348 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
Steve Block6ded16b2010-05-10 14:33:55 +01001349 Handle<SharedFunctionInfo> shared =
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001350 Factory::NewSharedFunctionInfo(name, literals, code,
1351 Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
Steve Block6ded16b2010-05-10 14:33:55 +01001352 shared->set_construct_stub(*construct_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +00001353
Steve Block6ded16b2010-05-10 14:33:55 +01001354 // Copy the function data to the shared function info.
1355 shared->set_function_data(fun->shared()->function_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00001356 int parameters = fun->shared()->formal_parameter_count();
Steve Block6ded16b2010-05-10 14:33:55 +01001357 shared->set_formal_parameter_count(parameters);
Steve Blocka7e24c12009-10-30 11:49:00 +00001358
1359 // TODO(1240846): It's weird that native function declarations are
1360 // introduced dynamically when we meet their declarations, whereas
1361 // other functions are setup when entering the surrounding scope.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001362 SharedFunctionInfoLiteral* lit = new SharedFunctionInfoLiteral(shared);
Steve Blocka7e24c12009-10-30 11:49:00 +00001363 VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001364 return new ExpressionStatement(
1365 new Assignment(Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
Steve Blocka7e24c12009-10-30 11:49:00 +00001366}
1367
1368
1369Statement* Parser::ParseFunctionDeclaration(bool* ok) {
1370 // FunctionDeclaration ::
1371 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1372 Expect(Token::FUNCTION, CHECK_OK);
1373 int function_token_position = scanner().location().beg_pos;
1374 Handle<String> name = ParseIdentifier(CHECK_OK);
1375 FunctionLiteral* fun = ParseFunctionLiteral(name,
1376 function_token_position,
1377 DECLARATION,
1378 CHECK_OK);
1379 // Even if we're not at the top-level of the global or a function
1380 // scope, we treat is as such and introduce the function with it's
1381 // initial value upon entering the corresponding scope.
1382 Declare(name, Variable::VAR, fun, true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001383 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001384}
1385
1386
1387Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
1388 // Block ::
1389 // '{' Statement* '}'
1390
1391 // Note that a Block does not introduce a new execution scope!
1392 // (ECMA-262, 3rd, 12.2)
1393 //
1394 // Construct block expecting 16 statements.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001395 Block* result = new Block(labels, 16, false);
1396 Target target(&this->target_stack_, result);
Steve Blocka7e24c12009-10-30 11:49:00 +00001397 Expect(Token::LBRACE, CHECK_OK);
1398 while (peek() != Token::RBRACE) {
1399 Statement* stat = ParseStatement(NULL, CHECK_OK);
1400 if (stat && !stat->IsEmpty()) result->AddStatement(stat);
1401 }
1402 Expect(Token::RBRACE, CHECK_OK);
1403 return result;
1404}
1405
1406
1407Block* Parser::ParseVariableStatement(bool* ok) {
1408 // VariableStatement ::
1409 // VariableDeclarations ';'
1410
1411 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature
1412 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK);
1413 ExpectSemicolon(CHECK_OK);
1414 return result;
1415}
1416
1417
1418// If the variable declaration declares exactly one non-const
1419// variable, then *var is set to that variable. In all other cases,
1420// *var is untouched; in particular, it is the caller's responsibility
1421// to initialize it properly. This mechanism is used for the parsing
1422// of 'for-in' loops.
1423Block* Parser::ParseVariableDeclarations(bool accept_IN,
1424 Expression** var,
1425 bool* ok) {
1426 // VariableDeclarations ::
1427 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
1428
1429 Variable::Mode mode = Variable::VAR;
1430 bool is_const = false;
1431 if (peek() == Token::VAR) {
1432 Consume(Token::VAR);
1433 } else if (peek() == Token::CONST) {
1434 Consume(Token::CONST);
1435 mode = Variable::CONST;
1436 is_const = true;
1437 } else {
1438 UNREACHABLE(); // by current callers
1439 }
1440
1441 // The scope of a variable/const declared anywhere inside a function
1442 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
1443 // transform a source-level variable/const declaration into a (Function)
1444 // Scope declaration, and rewrite the source-level initialization into an
1445 // assignment statement. We use a block to collect multiple assignments.
1446 //
1447 // We mark the block as initializer block because we don't want the
1448 // rewriter to add a '.result' assignment to such a block (to get compliant
1449 // behavior for code such as print(eval('var x = 7')), and for cosmetic
1450 // reasons when pretty-printing. Also, unless an assignment (initialization)
1451 // is inside an initializer block, it is ignored.
1452 //
1453 // Create new block with one expected declaration.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001454 Block* block = new Block(NULL, 1, true);
Steve Blocka7e24c12009-10-30 11:49:00 +00001455 VariableProxy* last_var = NULL; // the last variable declared
1456 int nvars = 0; // the number of variables declared
1457 do {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001458 if (fni_ != NULL) fni_->Enter();
1459
Steve Blocka7e24c12009-10-30 11:49:00 +00001460 // Parse variable name.
1461 if (nvars > 0) Consume(Token::COMMA);
1462 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001463 if (fni_ != NULL) fni_->PushVariableName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001464
1465 // Declare variable.
1466 // Note that we *always* must treat the initial value via a separate init
1467 // assignment for variables and constants because the value must be assigned
1468 // when the variable is encountered in the source. But the variable/constant
1469 // is declared (and set to 'undefined') upon entering the function within
1470 // which the variable or constant is declared. Only function variables have
1471 // an initial value in the declaration (because they are initialized upon
1472 // entering the function).
1473 //
1474 // If we have a const declaration, in an inner scope, the proxy is always
1475 // bound to the declared variable (independent of possibly surrounding with
1476 // statements).
1477 last_var = Declare(name, mode, NULL,
1478 is_const /* always bound for CONST! */,
1479 CHECK_OK);
1480 nvars++;
1481
1482 // Parse initialization expression if present and/or needed. A
1483 // declaration of the form:
1484 //
1485 // var v = x;
1486 //
1487 // is syntactic sugar for:
1488 //
1489 // var v; v = x;
1490 //
1491 // In particular, we need to re-lookup 'v' as it may be a
1492 // different 'v' than the 'v' in the declaration (if we are inside
1493 // a 'with' statement that makes a object property with name 'v'
1494 // visible).
1495 //
1496 // However, note that const declarations are different! A const
1497 // declaration of the form:
1498 //
1499 // const c = x;
1500 //
1501 // is *not* syntactic sugar for:
1502 //
1503 // const c; c = x;
1504 //
1505 // The "variable" c initialized to x is the same as the declared
1506 // one - there is no re-lookup (see the last parameter of the
1507 // Declare() call above).
1508
1509 Expression* value = NULL;
1510 int position = -1;
1511 if (peek() == Token::ASSIGN) {
1512 Expect(Token::ASSIGN, CHECK_OK);
1513 position = scanner().location().beg_pos;
1514 value = ParseAssignmentExpression(accept_IN, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001515 // Don't infer if it is "a = function(){...}();"-like expression.
1516 if (fni_ != NULL && value->AsCall() == NULL) fni_->Infer();
Steve Blocka7e24c12009-10-30 11:49:00 +00001517 }
1518
1519 // Make sure that 'const c' actually initializes 'c' to undefined
1520 // even though it seems like a stupid thing to do.
1521 if (value == NULL && is_const) {
1522 value = GetLiteralUndefined();
1523 }
1524
1525 // Global variable declarations must be compiled in a specific
1526 // way. When the script containing the global variable declaration
1527 // is entered, the global variable must be declared, so that if it
1528 // doesn't exist (not even in a prototype of the global object) it
1529 // gets created with an initial undefined value. This is handled
1530 // by the declarations part of the function representing the
1531 // top-level global code; see Runtime::DeclareGlobalVariable. If
1532 // it already exists (in the object or in a prototype), it is
1533 // *not* touched until the variable declaration statement is
1534 // executed.
1535 //
1536 // Executing the variable declaration statement will always
1537 // guarantee to give the global object a "local" variable; a
1538 // variable defined in the global object and not in any
1539 // prototype. This way, global variable declarations can shadow
1540 // properties in the prototype chain, but only after the variable
1541 // declaration statement has been executed. This is important in
1542 // browsers where the global object (window) has lots of
1543 // properties defined in prototype objects.
1544
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001545 if (top_scope_->is_global_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001546 // Compute the arguments for the runtime call.
1547 ZoneList<Expression*>* arguments = new ZoneList<Expression*>(2);
1548 // Be careful not to assign a value to the global variable if
1549 // we're in a with. The initialization value should not
1550 // necessarily be stored in the global object in that case,
1551 // which is why we need to generate a separate assignment node.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001552 arguments->Add(new Literal(name)); // we have at least 1 parameter
Steve Blocka7e24c12009-10-30 11:49:00 +00001553 if (is_const || (value != NULL && !inside_with())) {
1554 arguments->Add(value);
1555 value = NULL; // zap the value to avoid the unnecessary assignment
1556 }
1557 // Construct the call to Runtime::DeclareGlobal{Variable,Const}Locally
1558 // and add it to the initialization statement block. Note that
1559 // this function does different things depending on if we have
1560 // 1 or 2 parameters.
1561 CallRuntime* initialize;
1562 if (is_const) {
1563 initialize =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001564 new CallRuntime(
Steve Blocka7e24c12009-10-30 11:49:00 +00001565 Factory::InitializeConstGlobal_symbol(),
1566 Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001567 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001568 } else {
1569 initialize =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001570 new CallRuntime(
Steve Blocka7e24c12009-10-30 11:49:00 +00001571 Factory::InitializeVarGlobal_symbol(),
1572 Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001573 arguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001574 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001575 block->AddStatement(new ExpressionStatement(initialize));
Steve Blocka7e24c12009-10-30 11:49:00 +00001576 }
1577
1578 // Add an assignment node to the initialization statement block if
1579 // we still have a pending initialization value. We must distinguish
1580 // between variables and constants: Variable initializations are simply
1581 // assignments (with all the consequences if they are inside a 'with'
1582 // statement - they may change a 'with' object property). Constant
1583 // initializations always assign to the declared constant which is
1584 // always at the function scope level. This is only relevant for
1585 // dynamically looked-up variables and constants (the start context
1586 // for constant lookups is always the function context, while it is
1587 // the top context for variables). Sigh...
1588 if (value != NULL) {
1589 Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001590 Assignment* assignment = new Assignment(op, last_var, value, position);
1591 if (block) block->AddStatement(new ExpressionStatement(assignment));
Steve Blocka7e24c12009-10-30 11:49:00 +00001592 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001593
1594 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00001595 } while (peek() == Token::COMMA);
1596
1597 if (!is_const && nvars == 1) {
1598 // We have a single, non-const variable.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001599 ASSERT(last_var != NULL);
1600 *var = last_var;
Steve Blocka7e24c12009-10-30 11:49:00 +00001601 }
1602
1603 return block;
1604}
1605
1606
1607static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
1608 ASSERT(!label.is_null());
1609 if (labels != NULL)
1610 for (int i = labels->length(); i-- > 0; )
1611 if (labels->at(i).is_identical_to(label))
1612 return true;
1613
1614 return false;
1615}
1616
1617
1618Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
1619 bool* ok) {
1620 // ExpressionStatement | LabelledStatement ::
1621 // Expression ';'
1622 // Identifier ':' Statement
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001623 bool starts_with_idenfifier = (peek() == Token::IDENTIFIER);
Steve Blocka7e24c12009-10-30 11:49:00 +00001624 Expression* expr = ParseExpression(true, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001625 if (peek() == Token::COLON && starts_with_idenfifier && expr &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001626 expr->AsVariableProxy() != NULL &&
1627 !expr->AsVariableProxy()->is_this()) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001628 // Expression is a single identifier, and not, e.g., a parenthesized
1629 // identifier.
Steve Blocka7e24c12009-10-30 11:49:00 +00001630 VariableProxy* var = expr->AsVariableProxy();
1631 Handle<String> label = var->name();
1632 // TODO(1240780): We don't check for redeclaration of labels
1633 // during preparsing since keeping track of the set of active
1634 // labels requires nontrivial changes to the way scopes are
1635 // structured. However, these are probably changes we want to
1636 // make later anyway so we should go back and fix this then.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001637 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
1638 SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
1639 const char* elms[2] = { "Label", *c_string };
1640 Vector<const char*> args(elms, 2);
1641 ReportMessage("redeclaration", args);
1642 *ok = false;
1643 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001644 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001645 if (labels == NULL) labels = new ZoneStringList(4);
1646 labels->Add(label);
1647 // Remove the "ghost" variable that turned out to be a label
1648 // from the top scope. This way, we don't try to resolve it
1649 // during the scope processing.
1650 top_scope_->RemoveUnresolved(var);
Steve Blocka7e24c12009-10-30 11:49:00 +00001651 Expect(Token::COLON, CHECK_OK);
1652 return ParseStatement(labels, ok);
1653 }
1654
1655 // Parsed expression statement.
1656 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001657 return new ExpressionStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001658}
1659
1660
1661IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
1662 // IfStatement ::
1663 // 'if' '(' Expression ')' Statement ('else' Statement)?
1664
1665 Expect(Token::IF, CHECK_OK);
1666 Expect(Token::LPAREN, CHECK_OK);
1667 Expression* condition = ParseExpression(true, CHECK_OK);
1668 Expect(Token::RPAREN, CHECK_OK);
1669 Statement* then_statement = ParseStatement(labels, CHECK_OK);
1670 Statement* else_statement = NULL;
1671 if (peek() == Token::ELSE) {
1672 Next();
1673 else_statement = ParseStatement(labels, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001674 } else {
1675 else_statement = EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001676 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001677 return new IfStatement(condition, then_statement, else_statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00001678}
1679
1680
1681Statement* Parser::ParseContinueStatement(bool* ok) {
1682 // ContinueStatement ::
1683 // 'continue' Identifier? ';'
1684
1685 Expect(Token::CONTINUE, CHECK_OK);
1686 Handle<String> label = Handle<String>::null();
1687 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001688 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001689 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1690 label = ParseIdentifier(CHECK_OK);
1691 }
1692 IterationStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001693 target = LookupContinueTarget(label, CHECK_OK);
1694 if (target == NULL) {
1695 // Illegal continue statement. To be consistent with KJS we delay
1696 // reporting of the syntax error until runtime.
1697 Handle<String> error_type = Factory::illegal_continue_symbol();
1698 if (!label.is_null()) error_type = Factory::unknown_label_symbol();
1699 Expression* throw_error = NewThrowSyntaxError(error_type, label);
1700 return new ExpressionStatement(throw_error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001701 }
1702 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001703 return new ContinueStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001704}
1705
1706
1707Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
1708 // BreakStatement ::
1709 // 'break' Identifier? ';'
1710
1711 Expect(Token::BREAK, CHECK_OK);
1712 Handle<String> label;
1713 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001714 if (!scanner().has_line_terminator_before_next() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001715 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
1716 label = ParseIdentifier(CHECK_OK);
1717 }
1718 // Parse labeled break statements that target themselves into
1719 // empty statements, e.g. 'l1: l2: l3: break l2;'
1720 if (!label.is_null() && ContainsLabel(labels, label)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001721 return EmptyStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00001722 }
1723 BreakableStatement* target = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001724 target = LookupBreakTarget(label, CHECK_OK);
1725 if (target == NULL) {
1726 // Illegal break statement. To be consistent with KJS we delay
1727 // reporting of the syntax error until runtime.
1728 Handle<String> error_type = Factory::illegal_break_symbol();
1729 if (!label.is_null()) error_type = Factory::unknown_label_symbol();
1730 Expression* throw_error = NewThrowSyntaxError(error_type, label);
1731 return new ExpressionStatement(throw_error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001732 }
1733 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001734 return new BreakStatement(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001735}
1736
1737
1738Statement* Parser::ParseReturnStatement(bool* ok) {
1739 // ReturnStatement ::
1740 // 'return' Expression? ';'
1741
1742 // Consume the return token. It is necessary to do the before
1743 // reporting any errors on it, because of the way errors are
1744 // reported (underlining).
1745 Expect(Token::RETURN, CHECK_OK);
1746
1747 // An ECMAScript program is considered syntactically incorrect if it
1748 // contains a return statement that is not within the body of a
1749 // function. See ECMA-262, section 12.9, page 67.
1750 //
1751 // To be consistent with KJS we report the syntax error at runtime.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001752 if (!top_scope_->is_function_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001753 Handle<String> type = Factory::illegal_return_symbol();
1754 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001755 return new ExpressionStatement(throw_error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001756 }
1757
1758 Token::Value tok = peek();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001759 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00001760 tok == Token::SEMICOLON ||
1761 tok == Token::RBRACE ||
1762 tok == Token::EOS) {
1763 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001764 return new ReturnStatement(GetLiteralUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00001765 }
1766
1767 Expression* expr = ParseExpression(true, CHECK_OK);
1768 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001769 return new ReturnStatement(expr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001770}
1771
1772
1773Block* Parser::WithHelper(Expression* obj,
1774 ZoneStringList* labels,
1775 bool is_catch_block,
1776 bool* ok) {
1777 // Parse the statement and collect escaping labels.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001778 ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001779 TargetCollector collector(target_list);
1780 Statement* stat;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001781 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00001782 with_nesting_level_++;
1783 top_scope_->RecordWithStatement();
1784 stat = ParseStatement(labels, CHECK_OK);
1785 with_nesting_level_--;
1786 }
1787 // Create resulting block with two statements.
1788 // 1: Evaluate the with expression.
1789 // 2: The try-finally block evaluating the body.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001790 Block* result = new Block(NULL, 2, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001791
1792 if (result != NULL) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001793 result->AddStatement(new WithEnterStatement(obj, is_catch_block));
Steve Blocka7e24c12009-10-30 11:49:00 +00001794
1795 // Create body block.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001796 Block* body = new Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001797 body->AddStatement(stat);
1798
1799 // Create exit block.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001800 Block* exit = new Block(NULL, 1, false);
1801 exit->AddStatement(new WithExitStatement());
Steve Blocka7e24c12009-10-30 11:49:00 +00001802
1803 // Return a try-finally statement.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001804 TryFinallyStatement* wrapper = new TryFinallyStatement(body, exit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001805 wrapper->set_escaping_targets(collector.targets());
1806 result->AddStatement(wrapper);
1807 }
1808 return result;
1809}
1810
1811
1812Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
1813 // WithStatement ::
1814 // 'with' '(' Expression ')' Statement
1815
1816 Expect(Token::WITH, CHECK_OK);
1817 Expect(Token::LPAREN, CHECK_OK);
1818 Expression* expr = ParseExpression(true, CHECK_OK);
1819 Expect(Token::RPAREN, CHECK_OK);
1820
1821 return WithHelper(expr, labels, false, CHECK_OK);
1822}
1823
1824
1825CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
1826 // CaseClause ::
1827 // 'case' Expression ':' Statement*
1828 // 'default' ':' Statement*
1829
1830 Expression* label = NULL; // NULL expression indicates default case
1831 if (peek() == Token::CASE) {
1832 Expect(Token::CASE, CHECK_OK);
1833 label = ParseExpression(true, CHECK_OK);
1834 } else {
1835 Expect(Token::DEFAULT, CHECK_OK);
1836 if (*default_seen_ptr) {
1837 ReportMessage("multiple_defaults_in_switch",
1838 Vector<const char*>::empty());
1839 *ok = false;
1840 return NULL;
1841 }
1842 *default_seen_ptr = true;
1843 }
1844 Expect(Token::COLON, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001845 int pos = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001846 ZoneList<Statement*>* statements = new ZoneList<Statement*>(5);
Steve Blocka7e24c12009-10-30 11:49:00 +00001847 while (peek() != Token::CASE &&
1848 peek() != Token::DEFAULT &&
1849 peek() != Token::RBRACE) {
1850 Statement* stat = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001851 statements->Add(stat);
Steve Blocka7e24c12009-10-30 11:49:00 +00001852 }
1853
Ben Murdochb0fe1622011-05-05 13:52:32 +01001854 return new CaseClause(label, statements, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001855}
1856
1857
1858SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
1859 bool* ok) {
1860 // SwitchStatement ::
1861 // 'switch' '(' Expression ')' '{' CaseClause* '}'
1862
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001863 SwitchStatement* statement = new SwitchStatement(labels);
1864 Target target(&this->target_stack_, statement);
Steve Blocka7e24c12009-10-30 11:49:00 +00001865
1866 Expect(Token::SWITCH, CHECK_OK);
1867 Expect(Token::LPAREN, CHECK_OK);
1868 Expression* tag = ParseExpression(true, CHECK_OK);
1869 Expect(Token::RPAREN, CHECK_OK);
1870
1871 bool default_seen = false;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001872 ZoneList<CaseClause*>* cases = new ZoneList<CaseClause*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001873 Expect(Token::LBRACE, CHECK_OK);
1874 while (peek() != Token::RBRACE) {
1875 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001876 cases->Add(clause);
Steve Blocka7e24c12009-10-30 11:49:00 +00001877 }
1878 Expect(Token::RBRACE, CHECK_OK);
1879
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001880 if (statement) statement->Initialize(tag, cases);
Steve Blocka7e24c12009-10-30 11:49:00 +00001881 return statement;
1882}
1883
1884
1885Statement* Parser::ParseThrowStatement(bool* ok) {
1886 // ThrowStatement ::
1887 // 'throw' Expression ';'
1888
1889 Expect(Token::THROW, CHECK_OK);
1890 int pos = scanner().location().beg_pos;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001891 if (scanner().has_line_terminator_before_next()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001892 ReportMessage("newline_after_throw", Vector<const char*>::empty());
1893 *ok = false;
1894 return NULL;
1895 }
1896 Expression* exception = ParseExpression(true, CHECK_OK);
1897 ExpectSemicolon(CHECK_OK);
1898
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001899 return new ExpressionStatement(new Throw(exception, pos));
Steve Blocka7e24c12009-10-30 11:49:00 +00001900}
1901
1902
1903TryStatement* Parser::ParseTryStatement(bool* ok) {
1904 // TryStatement ::
1905 // 'try' Block Catch
1906 // 'try' Block Finally
1907 // 'try' Block Catch Finally
1908 //
1909 // Catch ::
1910 // 'catch' '(' Identifier ')' Block
1911 //
1912 // Finally ::
1913 // 'finally' Block
1914
1915 Expect(Token::TRY, CHECK_OK);
1916
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001917 ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001918 TargetCollector collector(target_list);
1919 Block* try_block;
1920
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001921 { Target target(&this->target_stack_, &collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00001922 try_block = ParseBlock(NULL, CHECK_OK);
1923 }
1924
1925 Block* catch_block = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001926 Variable* catch_var = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001927 Block* finally_block = NULL;
1928
1929 Token::Value tok = peek();
1930 if (tok != Token::CATCH && tok != Token::FINALLY) {
1931 ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
1932 *ok = false;
1933 return NULL;
1934 }
1935
1936 // If we can break out from the catch block and there is a finally block,
1937 // then we will need to collect jump targets from the catch block. Since
1938 // we don't know yet if there will be a finally block, we always collect
1939 // the jump targets.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001940 ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001941 TargetCollector catch_collector(catch_target_list);
1942 bool has_catch = false;
1943 if (tok == Token::CATCH) {
1944 has_catch = true;
1945 Consume(Token::CATCH);
1946
1947 Expect(Token::LPAREN, CHECK_OK);
1948 Handle<String> name = ParseIdentifier(CHECK_OK);
1949 Expect(Token::RPAREN, CHECK_OK);
1950
1951 if (peek() == Token::LBRACE) {
1952 // Allocate a temporary for holding the finally state while
1953 // executing the finally block.
1954 catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001955 Literal* name_literal = new Literal(name);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001956 VariableProxy* catch_var_use = new VariableProxy(catch_var);
1957 Expression* obj = new CatchExtensionObject(name_literal, catch_var_use);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001958 { Target target(&this->target_stack_, &catch_collector);
Steve Blocka7e24c12009-10-30 11:49:00 +00001959 catch_block = WithHelper(obj, NULL, true, CHECK_OK);
1960 }
1961 } else {
1962 Expect(Token::LBRACE, CHECK_OK);
1963 }
1964
1965 tok = peek();
1966 }
1967
1968 if (tok == Token::FINALLY || !has_catch) {
1969 Consume(Token::FINALLY);
1970 // Declare a variable for holding the finally state while
1971 // executing the finally block.
1972 finally_block = ParseBlock(NULL, CHECK_OK);
1973 }
1974
1975 // Simplify the AST nodes by converting:
1976 // 'try { } catch { } finally { }'
1977 // to:
1978 // 'try { try { } catch { } } finally { }'
1979
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001980 if (catch_block != NULL && finally_block != NULL) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001981 VariableProxy* catch_var_defn = new VariableProxy(catch_var);
Steve Block3ce2e202009-11-05 08:53:23 +00001982 TryCatchStatement* statement =
Ben Murdochb0fe1622011-05-05 13:52:32 +01001983 new TryCatchStatement(try_block, catch_var_defn, catch_block);
Steve Blocka7e24c12009-10-30 11:49:00 +00001984 statement->set_escaping_targets(collector.targets());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001985 try_block = new Block(NULL, 1, false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001986 try_block->AddStatement(statement);
1987 catch_block = NULL;
1988 }
1989
1990 TryStatement* result = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001991 if (catch_block != NULL) {
1992 ASSERT(finally_block == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001993 VariableProxy* catch_var_defn = new VariableProxy(catch_var);
1994 result = new TryCatchStatement(try_block, catch_var_defn, catch_block);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001995 result->set_escaping_targets(collector.targets());
1996 } else {
1997 ASSERT(finally_block != NULL);
1998 result = new TryFinallyStatement(try_block, finally_block);
1999 // Add the jump targets of the try block and the catch block.
2000 for (int i = 0; i < collector.targets()->length(); i++) {
2001 catch_collector.AddTarget(collector.targets()->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00002002 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002003 result->set_escaping_targets(catch_collector.targets());
Steve Blocka7e24c12009-10-30 11:49:00 +00002004 }
2005
2006 return result;
2007}
2008
2009
Steve Block3ce2e202009-11-05 08:53:23 +00002010DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
2011 bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002012 // DoStatement ::
2013 // 'do' Statement 'while' '(' Expression ')' ';'
2014
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002015 temp_scope_->AddLoop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002016 DoWhileStatement* loop = new DoWhileStatement(labels);
2017 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002018
2019 Expect(Token::DO, CHECK_OK);
2020 Statement* body = ParseStatement(NULL, CHECK_OK);
2021 Expect(Token::WHILE, CHECK_OK);
2022 Expect(Token::LPAREN, CHECK_OK);
Steve Blockd0582a62009-12-15 09:54:21 +00002023
2024 if (loop != NULL) {
2025 int position = scanner().location().beg_pos;
2026 loop->set_condition_position(position);
2027 }
2028
Steve Blocka7e24c12009-10-30 11:49:00 +00002029 Expression* cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002030 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002031 Expect(Token::RPAREN, CHECK_OK);
2032
2033 // Allow do-statements to be terminated with and without
2034 // semi-colons. This allows code such as 'do;while(0)return' to
2035 // parse, which would not be the case if we had used the
2036 // ExpectSemicolon() functionality here.
2037 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2038
Steve Block3ce2e202009-11-05 08:53:23 +00002039 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002040 return loop;
2041}
2042
2043
Steve Block3ce2e202009-11-05 08:53:23 +00002044WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002045 // WhileStatement ::
2046 // 'while' '(' Expression ')' Statement
2047
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002048 temp_scope_->AddLoop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002049 WhileStatement* loop = new WhileStatement(labels);
2050 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002051
2052 Expect(Token::WHILE, CHECK_OK);
2053 Expect(Token::LPAREN, CHECK_OK);
2054 Expression* cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002055 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002056 Expect(Token::RPAREN, CHECK_OK);
2057 Statement* body = ParseStatement(NULL, CHECK_OK);
2058
Steve Block3ce2e202009-11-05 08:53:23 +00002059 if (loop != NULL) loop->Initialize(cond, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002060 return loop;
2061}
2062
2063
2064Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
2065 // ForStatement ::
2066 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
2067
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002068 temp_scope_->AddLoop();
Steve Blocka7e24c12009-10-30 11:49:00 +00002069 Statement* init = NULL;
2070
2071 Expect(Token::FOR, CHECK_OK);
2072 Expect(Token::LPAREN, CHECK_OK);
2073 if (peek() != Token::SEMICOLON) {
2074 if (peek() == Token::VAR || peek() == Token::CONST) {
2075 Expression* each = NULL;
2076 Block* variable_statement =
2077 ParseVariableDeclarations(false, &each, CHECK_OK);
2078 if (peek() == Token::IN && each != NULL) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002079 ForInStatement* loop = new ForInStatement(labels);
2080 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002081
2082 Expect(Token::IN, CHECK_OK);
2083 Expression* enumerable = ParseExpression(true, CHECK_OK);
2084 Expect(Token::RPAREN, CHECK_OK);
2085
2086 Statement* body = ParseStatement(NULL, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002087 loop->Initialize(each, enumerable, body);
2088 Block* result = new Block(NULL, 2, false);
2089 result->AddStatement(variable_statement);
2090 result->AddStatement(loop);
2091 // Parsed for-in loop w/ variable/const declaration.
2092 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00002093 } else {
2094 init = variable_statement;
2095 }
2096
2097 } else {
2098 Expression* expression = ParseExpression(false, CHECK_OK);
2099 if (peek() == Token::IN) {
2100 // Signal a reference error if the expression is an invalid
2101 // left-hand side expression. We could report this as a syntax
2102 // error here but for compatibility with JSC we choose to report
2103 // the error at runtime.
2104 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2105 Handle<String> type = Factory::invalid_lhs_in_for_in_symbol();
2106 expression = NewThrowReferenceError(type);
2107 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002108 ForInStatement* loop = new ForInStatement(labels);
2109 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002110
2111 Expect(Token::IN, CHECK_OK);
2112 Expression* enumerable = ParseExpression(true, CHECK_OK);
2113 Expect(Token::RPAREN, CHECK_OK);
2114
2115 Statement* body = ParseStatement(NULL, CHECK_OK);
2116 if (loop) loop->Initialize(expression, enumerable, body);
Steve Blocka7e24c12009-10-30 11:49:00 +00002117 // Parsed for-in loop.
2118 return loop;
2119
2120 } else {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002121 init = new ExpressionStatement(expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002122 }
2123 }
2124 }
2125
2126 // Standard 'for' loop
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002127 ForStatement* loop = new ForStatement(labels);
2128 Target target(&this->target_stack_, loop);
Steve Blocka7e24c12009-10-30 11:49:00 +00002129
2130 // Parsed initializer at this point.
2131 Expect(Token::SEMICOLON, CHECK_OK);
2132
2133 Expression* cond = NULL;
2134 if (peek() != Token::SEMICOLON) {
2135 cond = ParseExpression(true, CHECK_OK);
Steve Block6ded16b2010-05-10 14:33:55 +01002136 if (cond != NULL) cond->set_is_loop_condition(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002137 }
2138 Expect(Token::SEMICOLON, CHECK_OK);
2139
2140 Statement* next = NULL;
2141 if (peek() != Token::RPAREN) {
2142 Expression* exp = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002143 next = new ExpressionStatement(exp);
Steve Blocka7e24c12009-10-30 11:49:00 +00002144 }
2145 Expect(Token::RPAREN, CHECK_OK);
2146
2147 Statement* body = ParseStatement(NULL, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00002148 if (loop) loop->Initialize(init, cond, next, body);
2149 return loop;
2150}
2151
2152
2153// Precedence = 1
2154Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
2155 // Expression ::
2156 // AssignmentExpression
2157 // Expression ',' AssignmentExpression
2158
2159 Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
2160 while (peek() == Token::COMMA) {
2161 Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002162 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002163 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002164 result = new BinaryOperation(Token::COMMA, result, right, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002165 }
2166 return result;
2167}
2168
2169
2170// Precedence = 2
2171Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
2172 // AssignmentExpression ::
2173 // ConditionalExpression
2174 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2175
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002176 if (fni_ != NULL) fni_->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00002177 Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
2178
2179 if (!Token::IsAssignmentOp(peek())) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002180 if (fni_ != NULL) fni_->Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +00002181 // Parsed conditional expression only (no assignment).
2182 return expression;
2183 }
2184
2185 // Signal a reference error if the expression is an invalid left-hand
2186 // side expression. We could report this as a syntax error here but
2187 // for compatibility with JSC we choose to report the error at
2188 // runtime.
2189 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2190 Handle<String> type = Factory::invalid_lhs_in_assignment_symbol();
2191 expression = NewThrowReferenceError(type);
2192 }
2193
2194 Token::Value op = Next(); // Get assignment operator.
2195 int pos = scanner().location().beg_pos;
2196 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2197
2198 // TODO(1231235): We try to estimate the set of properties set by
2199 // constructors. We define a new property whenever there is an
2200 // assignment to a property of 'this'. We should probably only add
2201 // properties if we haven't seen them before. Otherwise we'll
2202 // probably overestimate the number of properties.
2203 Property* property = expression ? expression->AsProperty() : NULL;
2204 if (op == Token::ASSIGN &&
2205 property != NULL &&
2206 property->obj()->AsVariableProxy() != NULL &&
2207 property->obj()->AsVariableProxy()->is_this()) {
2208 temp_scope_->AddProperty();
2209 }
2210
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002211 // If we assign a function literal to a property we pretenure the
2212 // literal so it can be added as a constant function property.
2213 if (property != NULL && right->AsFunctionLiteral() != NULL) {
2214 right->AsFunctionLiteral()->set_pretenure(true);
2215 }
2216
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002217 if (fni_ != NULL) {
2218 // Check if the right hand side is a call to avoid inferring a
2219 // name if we're dealing with "a = function(){...}();"-like
2220 // expression.
2221 if ((op == Token::INIT_VAR
2222 || op == Token::INIT_CONST
2223 || op == Token::ASSIGN)
2224 && (right->AsCall() == NULL)) {
2225 fni_->Infer();
2226 }
2227 fni_->Leave();
2228 }
2229
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002230 return new Assignment(op, expression, right, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002231}
2232
2233
2234// Precedence = 3
2235Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
2236 // ConditionalExpression ::
2237 // LogicalOrExpression
2238 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
2239
2240 // We start using the binary expression parser for prec >= 4 only!
2241 Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
2242 if (peek() != Token::CONDITIONAL) return expression;
2243 Consume(Token::CONDITIONAL);
2244 // In parsing the first assignment expression in conditional
2245 // expressions we always accept the 'in' keyword; see ECMA-262,
2246 // section 11.12, page 58.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002247 int left_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002248 Expression* left = ParseAssignmentExpression(true, CHECK_OK);
2249 Expect(Token::COLON, CHECK_OK);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002250 int right_position = scanner().peek_location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002251 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002252 return new Conditional(expression, left, right,
2253 left_position, right_position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002254}
2255
2256
2257static int Precedence(Token::Value tok, bool accept_IN) {
2258 if (tok == Token::IN && !accept_IN)
2259 return 0; // 0 precedence will terminate binary expression parsing
2260
2261 return Token::Precedence(tok);
2262}
2263
2264
2265// Precedence >= 4
2266Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
2267 ASSERT(prec >= 4);
2268 Expression* x = ParseUnaryExpression(CHECK_OK);
2269 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
2270 // prec1 >= 4
2271 while (Precedence(peek(), accept_IN) == prec1) {
2272 Token::Value op = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002273 int position = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00002274 Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
2275
2276 // Compute some expressions involving only number literals.
2277 if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
2278 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
2279 double x_val = x->AsLiteral()->handle()->Number();
2280 double y_val = y->AsLiteral()->handle()->Number();
2281
2282 switch (op) {
2283 case Token::ADD:
2284 x = NewNumberLiteral(x_val + y_val);
2285 continue;
2286 case Token::SUB:
2287 x = NewNumberLiteral(x_val - y_val);
2288 continue;
2289 case Token::MUL:
2290 x = NewNumberLiteral(x_val * y_val);
2291 continue;
2292 case Token::DIV:
2293 x = NewNumberLiteral(x_val / y_val);
2294 continue;
2295 case Token::BIT_OR:
2296 x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
2297 continue;
2298 case Token::BIT_AND:
2299 x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
2300 continue;
2301 case Token::BIT_XOR:
2302 x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
2303 continue;
2304 case Token::SHL: {
2305 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
2306 x = NewNumberLiteral(value);
2307 continue;
2308 }
2309 case Token::SHR: {
2310 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2311 uint32_t value = DoubleToUint32(x_val) >> shift;
2312 x = NewNumberLiteral(value);
2313 continue;
2314 }
2315 case Token::SAR: {
2316 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
2317 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
2318 x = NewNumberLiteral(value);
2319 continue;
2320 }
2321 default:
2322 break;
2323 }
2324 }
2325
Steve Blocka7e24c12009-10-30 11:49:00 +00002326 // For now we distinguish between comparisons and other binary
2327 // operations. (We could combine the two and get rid of this
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002328 // code and AST node eventually.)
Steve Blocka7e24c12009-10-30 11:49:00 +00002329 if (Token::IsCompareOp(op)) {
2330 // We have a comparison.
2331 Token::Value cmp = op;
2332 switch (op) {
2333 case Token::NE: cmp = Token::EQ; break;
2334 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
2335 default: break;
2336 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002337 x = NewCompareNode(cmp, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002338 if (cmp != op) {
2339 // The comparison was negated - add a NOT.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002340 x = new UnaryOperation(Token::NOT, x);
Steve Blocka7e24c12009-10-30 11:49:00 +00002341 }
2342
2343 } else {
2344 // We have a "normal" binary operation.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002345 x = new BinaryOperation(op, x, y, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002346 }
2347 }
2348 }
2349 return x;
2350}
2351
2352
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002353Expression* Parser::NewCompareNode(Token::Value op,
2354 Expression* x,
2355 Expression* y,
2356 int position) {
2357 ASSERT(op != Token::NE && op != Token::NE_STRICT);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002358 if (op == Token::EQ || op == Token::EQ_STRICT) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002359 bool is_strict = (op == Token::EQ_STRICT);
2360 Literal* x_literal = x->AsLiteral();
2361 if (x_literal != NULL && x_literal->IsNull()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002362 return new CompareToNull(is_strict, y);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002363 }
2364
2365 Literal* y_literal = y->AsLiteral();
2366 if (y_literal != NULL && y_literal->IsNull()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002367 return new CompareToNull(is_strict, x);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002368 }
2369 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002370 return new CompareOperation(op, x, y, position);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002371}
2372
2373
Steve Blocka7e24c12009-10-30 11:49:00 +00002374Expression* Parser::ParseUnaryExpression(bool* ok) {
2375 // UnaryExpression ::
2376 // PostfixExpression
2377 // 'delete' UnaryExpression
2378 // 'void' UnaryExpression
2379 // 'typeof' UnaryExpression
2380 // '++' UnaryExpression
2381 // '--' UnaryExpression
2382 // '+' UnaryExpression
2383 // '-' UnaryExpression
2384 // '~' UnaryExpression
2385 // '!' UnaryExpression
2386
2387 Token::Value op = peek();
2388 if (Token::IsUnaryOp(op)) {
2389 op = Next();
2390 Expression* expression = ParseUnaryExpression(CHECK_OK);
2391
2392 // Compute some expressions involving only number literals.
2393 if (expression != NULL && expression->AsLiteral() &&
2394 expression->AsLiteral()->handle()->IsNumber()) {
2395 double value = expression->AsLiteral()->handle()->Number();
2396 switch (op) {
2397 case Token::ADD:
2398 return expression;
2399 case Token::SUB:
2400 return NewNumberLiteral(-value);
2401 case Token::BIT_NOT:
2402 return NewNumberLiteral(~DoubleToInt32(value));
2403 default: break;
2404 }
2405 }
2406
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002407 return new UnaryOperation(op, expression);
Steve Blocka7e24c12009-10-30 11:49:00 +00002408
2409 } else if (Token::IsCountOp(op)) {
2410 op = Next();
2411 Expression* expression = ParseUnaryExpression(CHECK_OK);
2412 // Signal a reference error if the expression is an invalid
2413 // left-hand side expression. We could report this as a syntax
2414 // error here but for compatibility with JSC we choose to report the
2415 // error at runtime.
2416 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2417 Handle<String> type = Factory::invalid_lhs_in_prefix_op_symbol();
2418 expression = NewThrowReferenceError(type);
2419 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002420 int position = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002421 IncrementOperation* increment = new IncrementOperation(op, expression);
2422 return new CountOperation(true /* prefix */, increment, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002423
2424 } else {
2425 return ParsePostfixExpression(ok);
2426 }
2427}
2428
2429
2430Expression* Parser::ParsePostfixExpression(bool* ok) {
2431 // PostfixExpression ::
2432 // LeftHandSideExpression ('++' | '--')?
2433
2434 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002435 if (!scanner().has_line_terminator_before_next() &&
2436 Token::IsCountOp(peek())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002437 // Signal a reference error if the expression is an invalid
2438 // left-hand side expression. We could report this as a syntax
2439 // error here but for compatibility with JSC we choose to report the
2440 // error at runtime.
2441 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2442 Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol();
2443 expression = NewThrowReferenceError(type);
2444 }
2445 Token::Value next = Next();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002446 int position = scanner().location().beg_pos;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002447 IncrementOperation* increment = new IncrementOperation(next, expression);
2448 expression = new CountOperation(false /* postfix */, increment, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00002449 }
2450 return expression;
2451}
2452
2453
2454Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
2455 // LeftHandSideExpression ::
2456 // (NewExpression | MemberExpression) ...
2457
2458 Expression* result;
2459 if (peek() == Token::NEW) {
2460 result = ParseNewExpression(CHECK_OK);
2461 } else {
2462 result = ParseMemberExpression(CHECK_OK);
2463 }
2464
2465 while (true) {
2466 switch (peek()) {
2467 case Token::LBRACK: {
2468 Consume(Token::LBRACK);
2469 int pos = scanner().location().beg_pos;
2470 Expression* index = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002471 result = new Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002472 Expect(Token::RBRACK, CHECK_OK);
2473 break;
2474 }
2475
2476 case Token::LPAREN: {
2477 int pos = scanner().location().beg_pos;
2478 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2479
2480 // Keep track of eval() calls since they disable all local variable
2481 // optimizations.
2482 // The calls that need special treatment are the
2483 // direct (i.e. not aliased) eval calls. These calls are all of the
2484 // form eval(...) with no explicit receiver object where eval is not
2485 // declared in the current scope chain. These calls are marked as
2486 // potentially direct eval calls. Whether they are actually direct calls
2487 // to eval is determined at run time.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002488 VariableProxy* callee = result->AsVariableProxy();
2489 if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) {
2490 Handle<String> name = callee->name();
2491 Variable* var = top_scope_->Lookup(name);
2492 if (var == NULL) {
2493 top_scope_->RecordEvalCall();
Steve Blocka7e24c12009-10-30 11:49:00 +00002494 }
2495 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002496 result = NewCall(result, args, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002497 break;
2498 }
2499
2500 case Token::PERIOD: {
2501 Consume(Token::PERIOD);
2502 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002503 Handle<String> name = ParseIdentifierName(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002504 result = new Property(result, new Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002505 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002506 break;
2507 }
2508
2509 default:
2510 return result;
2511 }
2512 }
2513}
2514
2515
Steve Blocka7e24c12009-10-30 11:49:00 +00002516Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
2517 // NewExpression ::
2518 // ('new')+ MemberExpression
2519
2520 // The grammar for new expressions is pretty warped. The keyword
2521 // 'new' can either be a part of the new expression (where it isn't
2522 // followed by an argument list) or a part of the member expression,
2523 // where it must be followed by an argument list. To accommodate
2524 // this, we parse the 'new' keywords greedily and keep track of how
2525 // many we have parsed. This information is then passed on to the
2526 // member expression parser, which is only allowed to match argument
2527 // lists as long as it has 'new' prefixes left
2528 Expect(Token::NEW, CHECK_OK);
2529 PositionStack::Element pos(stack, scanner().location().beg_pos);
2530
2531 Expression* result;
2532 if (peek() == Token::NEW) {
2533 result = ParseNewPrefix(stack, CHECK_OK);
2534 } else {
2535 result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
2536 }
2537
2538 if (!stack->is_empty()) {
2539 int last = stack->pop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002540 result = new CallNew(result, new ZoneList<Expression*>(0), last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002541 }
2542 return result;
2543}
2544
2545
2546Expression* Parser::ParseNewExpression(bool* ok) {
2547 PositionStack stack(ok);
2548 return ParseNewPrefix(&stack, ok);
2549}
2550
2551
2552Expression* Parser::ParseMemberExpression(bool* ok) {
2553 return ParseMemberWithNewPrefixesExpression(NULL, ok);
2554}
2555
2556
2557Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
2558 bool* ok) {
2559 // MemberExpression ::
2560 // (PrimaryExpression | FunctionLiteral)
2561 // ('[' Expression ']' | '.' Identifier | Arguments)*
2562
2563 // Parse the initial primary or function expression.
2564 Expression* result = NULL;
2565 if (peek() == Token::FUNCTION) {
2566 Expect(Token::FUNCTION, CHECK_OK);
2567 int function_token_position = scanner().location().beg_pos;
2568 Handle<String> name;
2569 if (peek() == Token::IDENTIFIER) name = ParseIdentifier(CHECK_OK);
2570 result = ParseFunctionLiteral(name, function_token_position,
2571 NESTED, CHECK_OK);
2572 } else {
2573 result = ParsePrimaryExpression(CHECK_OK);
2574 }
2575
2576 while (true) {
2577 switch (peek()) {
2578 case Token::LBRACK: {
2579 Consume(Token::LBRACK);
2580 int pos = scanner().location().beg_pos;
2581 Expression* index = ParseExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002582 result = new Property(result, index, pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00002583 Expect(Token::RBRACK, CHECK_OK);
2584 break;
2585 }
2586 case Token::PERIOD: {
2587 Consume(Token::PERIOD);
2588 int pos = scanner().location().beg_pos;
Ben Murdochbb769b22010-08-11 14:56:33 +01002589 Handle<String> name = ParseIdentifierName(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002590 result = new Property(result, new Literal(name), pos);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002591 if (fni_ != NULL) fni_->PushLiteralName(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00002592 break;
2593 }
2594 case Token::LPAREN: {
2595 if ((stack == NULL) || stack->is_empty()) return result;
2596 // Consume one of the new prefixes (already parsed).
2597 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
2598 int last = stack->pop();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002599 result = new CallNew(result, args, last);
Steve Blocka7e24c12009-10-30 11:49:00 +00002600 break;
2601 }
2602 default:
2603 return result;
2604 }
2605 }
2606}
2607
2608
2609DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
2610 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
2611 // contexts this is used as a statement which invokes the debugger as i a
2612 // break point is present.
2613 // DebuggerStatement ::
2614 // 'debugger' ';'
2615
2616 Expect(Token::DEBUGGER, CHECK_OK);
2617 ExpectSemicolon(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002618 return new DebuggerStatement();
Steve Blocka7e24c12009-10-30 11:49:00 +00002619}
2620
2621
2622void Parser::ReportUnexpectedToken(Token::Value token) {
2623 // We don't report stack overflows here, to avoid increasing the
2624 // stack depth even further. Instead we report it after parsing is
Leon Clarke4515c472010-02-03 11:58:03 +00002625 // over, in ParseProgram/ParseJson.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002626 if (token == Token::ILLEGAL && stack_overflow_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002627 // Four of the tokens are treated specially
2628 switch (token) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002629 case Token::EOS:
2630 return ReportMessage("unexpected_eos", Vector<const char*>::empty());
2631 case Token::NUMBER:
2632 return ReportMessage("unexpected_token_number",
2633 Vector<const char*>::empty());
2634 case Token::STRING:
2635 return ReportMessage("unexpected_token_string",
2636 Vector<const char*>::empty());
2637 case Token::IDENTIFIER:
2638 return ReportMessage("unexpected_token_identifier",
2639 Vector<const char*>::empty());
2640 default:
2641 const char* name = Token::String(token);
2642 ASSERT(name != NULL);
2643 ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002644 }
2645}
2646
2647
Leon Clarkeac952652010-07-15 11:15:24 +01002648void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
2649 SmartPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
2650 const char* element[1] = { *name_string };
2651 ReportMessage("invalid_preparser_data",
2652 Vector<const char*>(element, 1));
2653 *ok = false;
2654}
2655
2656
Steve Blocka7e24c12009-10-30 11:49:00 +00002657Expression* Parser::ParsePrimaryExpression(bool* ok) {
2658 // PrimaryExpression ::
2659 // 'this'
2660 // 'null'
2661 // 'true'
2662 // 'false'
2663 // Identifier
2664 // Number
2665 // String
2666 // ArrayLiteral
2667 // ObjectLiteral
2668 // RegExpLiteral
2669 // '(' Expression ')'
2670
2671 Expression* result = NULL;
2672 switch (peek()) {
2673 case Token::THIS: {
2674 Consume(Token::THIS);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002675 VariableProxy* recv = top_scope_->receiver();
2676 result = recv;
Steve Blocka7e24c12009-10-30 11:49:00 +00002677 break;
2678 }
2679
2680 case Token::NULL_LITERAL:
2681 Consume(Token::NULL_LITERAL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002682 result = new Literal(Factory::null_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002683 break;
2684
2685 case Token::TRUE_LITERAL:
2686 Consume(Token::TRUE_LITERAL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002687 result = new Literal(Factory::true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002688 break;
2689
2690 case Token::FALSE_LITERAL:
2691 Consume(Token::FALSE_LITERAL);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002692 result = new Literal(Factory::false_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00002693 break;
2694
2695 case Token::IDENTIFIER: {
2696 Handle<String> name = ParseIdentifier(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002697 if (fni_ != NULL) fni_->PushVariableName(name);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002698 result = top_scope_->NewUnresolved(name, inside_with());
Steve Blocka7e24c12009-10-30 11:49:00 +00002699 break;
2700 }
2701
2702 case Token::NUMBER: {
2703 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01002704 ASSERT(scanner().is_literal_ascii());
2705 double value = StringToDouble(scanner().literal_ascii_string(),
2706 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00002707 result = NewNumberLiteral(value);
2708 break;
2709 }
2710
2711 case Token::STRING: {
2712 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01002713 Handle<String> symbol = GetSymbol(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002714 result = new Literal(symbol);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002715 if (fni_ != NULL) fni_->PushLiteralName(symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +00002716 break;
2717 }
2718
2719 case Token::ASSIGN_DIV:
2720 result = ParseRegExpLiteral(true, CHECK_OK);
2721 break;
2722
2723 case Token::DIV:
2724 result = ParseRegExpLiteral(false, CHECK_OK);
2725 break;
2726
2727 case Token::LBRACK:
2728 result = ParseArrayLiteral(CHECK_OK);
2729 break;
2730
2731 case Token::LBRACE:
2732 result = ParseObjectLiteral(CHECK_OK);
2733 break;
2734
2735 case Token::LPAREN:
2736 Consume(Token::LPAREN);
2737 result = ParseExpression(true, CHECK_OK);
2738 Expect(Token::RPAREN, CHECK_OK);
2739 break;
2740
2741 case Token::MOD:
2742 if (allow_natives_syntax_ || extension_ != NULL) {
2743 result = ParseV8Intrinsic(CHECK_OK);
2744 break;
2745 }
2746 // If we're not allowing special syntax we fall-through to the
2747 // default case.
2748
2749 default: {
Ben Murdochbb769b22010-08-11 14:56:33 +01002750 Token::Value tok = Next();
Steve Blocka7e24c12009-10-30 11:49:00 +00002751 ReportUnexpectedToken(tok);
2752 *ok = false;
2753 return NULL;
2754 }
2755 }
2756
2757 return result;
2758}
2759
2760
Leon Clarke4515c472010-02-03 11:58:03 +00002761void Parser::BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* values,
2762 Handle<FixedArray> literals,
2763 bool* is_simple,
2764 int* depth) {
2765 // Fill in the literals.
2766 // Accumulate output values in local variables.
2767 bool is_simple_acc = true;
2768 int depth_acc = 1;
2769 for (int i = 0; i < values->length(); i++) {
2770 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
2771 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
2772 depth_acc = m_literal->depth() + 1;
2773 }
2774 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
2775 if (boilerplate_value->IsUndefined()) {
2776 literals->set_the_hole(i);
2777 is_simple_acc = false;
2778 } else {
2779 literals->set(i, *boilerplate_value);
2780 }
2781 }
2782
2783 *is_simple = is_simple_acc;
2784 *depth = depth_acc;
2785}
2786
2787
Steve Blocka7e24c12009-10-30 11:49:00 +00002788Expression* Parser::ParseArrayLiteral(bool* ok) {
2789 // ArrayLiteral ::
2790 // '[' Expression? (',' Expression?)* ']'
2791
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002792 ZoneList<Expression*>* values = new ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00002793 Expect(Token::LBRACK, CHECK_OK);
2794 while (peek() != Token::RBRACK) {
2795 Expression* elem;
2796 if (peek() == Token::COMMA) {
2797 elem = GetLiteralTheHole();
2798 } else {
2799 elem = ParseAssignmentExpression(true, CHECK_OK);
2800 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002801 values->Add(elem);
Steve Blocka7e24c12009-10-30 11:49:00 +00002802 if (peek() != Token::RBRACK) {
2803 Expect(Token::COMMA, CHECK_OK);
2804 }
2805 }
2806 Expect(Token::RBRACK, CHECK_OK);
2807
2808 // Update the scope information before the pre-parsing bailout.
Steve Blocka7e24c12009-10-30 11:49:00 +00002809 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
2810
Steve Blocka7e24c12009-10-30 11:49:00 +00002811 // Allocate a fixed array with all the literals.
2812 Handle<FixedArray> literals =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002813 Factory::NewFixedArray(values->length(), TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00002814
2815 // Fill in the literals.
2816 bool is_simple = true;
2817 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002818 for (int i = 0, n = values->length(); i < n; i++) {
2819 MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
Steve Blocka7e24c12009-10-30 11:49:00 +00002820 if (m_literal != NULL && m_literal->depth() + 1 > depth) {
2821 depth = m_literal->depth() + 1;
2822 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002823 Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +00002824 if (boilerplate_value->IsUndefined()) {
2825 literals->set_the_hole(i);
2826 is_simple = false;
2827 } else {
2828 literals->set(i, *boilerplate_value);
2829 }
2830 }
2831
Iain Merrick75681382010-08-19 15:07:18 +01002832 // Simple and shallow arrays can be lazily copied, we transform the
2833 // elements array to a copy-on-write array.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002834 if (is_simple && depth == 1 && values->length() > 0) {
Iain Merrick75681382010-08-19 15:07:18 +01002835 literals->set_map(Heap::fixed_cow_array_map());
2836 }
2837
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002838 return new ArrayLiteral(literals, values,
2839 literal_index, is_simple, depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00002840}
2841
2842
2843bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
2844 return property != NULL &&
2845 property->kind() != ObjectLiteral::Property::PROTOTYPE;
2846}
2847
2848
2849bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002850 if (expression->AsLiteral() != NULL) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00002851 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
2852 return lit != NULL && lit->is_simple();
2853}
2854
Iain Merrick75681382010-08-19 15:07:18 +01002855
2856bool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
2857 Expression* value) {
2858 // If value is a literal the property value is already set in the
2859 // boilerplate object.
2860 if (value->AsLiteral() != NULL) return false;
2861 // If value is a materialized literal the property value is already set
2862 // in the boilerplate object if it is simple.
2863 if (CompileTimeValue::IsCompileTimeValue(value)) return false;
2864 return true;
2865}
2866
2867
Steve Blocka7e24c12009-10-30 11:49:00 +00002868Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
2869 ASSERT(IsCompileTimeValue(expression));
2870 Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED);
2871 ObjectLiteral* object_literal = expression->AsObjectLiteral();
2872 if (object_literal != NULL) {
2873 ASSERT(object_literal->is_simple());
Steve Block6ded16b2010-05-10 14:33:55 +01002874 if (object_literal->fast_elements()) {
2875 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
2876 } else {
2877 result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
2878 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002879 result->set(kElementsSlot, *object_literal->constant_properties());
2880 } else {
2881 ArrayLiteral* array_literal = expression->AsArrayLiteral();
2882 ASSERT(array_literal != NULL && array_literal->is_simple());
2883 result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
Leon Clarkee46be812010-01-19 14:06:41 +00002884 result->set(kElementsSlot, *array_literal->constant_elements());
Steve Blocka7e24c12009-10-30 11:49:00 +00002885 }
2886 return result;
2887}
2888
2889
2890CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
2891 Smi* type_value = Smi::cast(value->get(kTypeSlot));
2892 return static_cast<Type>(type_value->value());
2893}
2894
2895
2896Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
2897 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
2898}
2899
2900
2901Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
2902 if (expression->AsLiteral() != NULL) {
2903 return expression->AsLiteral()->handle();
2904 }
2905 if (CompileTimeValue::IsCompileTimeValue(expression)) {
2906 return CompileTimeValue::GetValue(expression);
2907 }
2908 return Factory::undefined_value();
2909}
2910
2911
Leon Clarke4515c472010-02-03 11:58:03 +00002912void Parser::BuildObjectLiteralConstantProperties(
2913 ZoneList<ObjectLiteral::Property*>* properties,
2914 Handle<FixedArray> constant_properties,
2915 bool* is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01002916 bool* fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00002917 int* depth) {
2918 int position = 0;
2919 // Accumulate the value in local variables and store it at the end.
2920 bool is_simple_acc = true;
2921 int depth_acc = 1;
Steve Block6ded16b2010-05-10 14:33:55 +01002922 uint32_t max_element_index = 0;
2923 uint32_t elements = 0;
Leon Clarke4515c472010-02-03 11:58:03 +00002924 for (int i = 0; i < properties->length(); i++) {
2925 ObjectLiteral::Property* property = properties->at(i);
2926 if (!IsBoilerplateProperty(property)) {
2927 is_simple_acc = false;
2928 continue;
2929 }
2930 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
2931 if (m_literal != NULL && m_literal->depth() >= depth_acc) {
2932 depth_acc = m_literal->depth() + 1;
2933 }
2934
2935 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
2936 // value for COMPUTED properties, the real value is filled in at
2937 // runtime. The enumeration order is maintained.
2938 Handle<Object> key = property->key()->handle();
2939 Handle<Object> value = GetBoilerplateValue(property->value());
2940 is_simple_acc = is_simple_acc && !value->IsUndefined();
2941
Steve Block6ded16b2010-05-10 14:33:55 +01002942 // Keep track of the number of elements in the object literal and
2943 // the largest element index. If the largest element index is
2944 // much larger than the number of elements, creating an object
2945 // literal with fast elements will be a waste of space.
2946 uint32_t element_index = 0;
2947 if (key->IsString()
2948 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
2949 && element_index > max_element_index) {
2950 max_element_index = element_index;
2951 elements++;
2952 } else if (key->IsSmi()) {
2953 int key_value = Smi::cast(*key)->value();
2954 if (key_value > 0
2955 && static_cast<uint32_t>(key_value) > max_element_index) {
2956 max_element_index = key_value;
2957 }
2958 elements++;
2959 }
2960
Leon Clarke4515c472010-02-03 11:58:03 +00002961 // Add name, value pair to the fixed array.
2962 constant_properties->set(position++, *key);
2963 constant_properties->set(position++, *value);
2964 }
Steve Block6ded16b2010-05-10 14:33:55 +01002965 *fast_elements =
2966 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
Leon Clarke4515c472010-02-03 11:58:03 +00002967 *is_simple = is_simple_acc;
2968 *depth = depth_acc;
2969}
2970
2971
Ben Murdochbb769b22010-08-11 14:56:33 +01002972ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
2973 bool* ok) {
2974 // Special handling of getter and setter syntax:
2975 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
2976 // We have already read the "get" or "set" keyword.
2977 Token::Value next = Next();
Steve Block9fac8402011-05-12 15:51:54 +01002978 bool is_keyword = Token::IsKeyword(next);
2979 if (next == Token::IDENTIFIER || next == Token::NUMBER ||
2980 next == Token::STRING || is_keyword) {
2981 Handle<String> name;
2982 if (is_keyword) {
2983 name = Factory::LookupAsciiSymbol(Token::String(next));
2984 } else {
2985 name = GetSymbol(CHECK_OK);
2986 }
Ben Murdochbb769b22010-08-11 14:56:33 +01002987 FunctionLiteral* value =
2988 ParseFunctionLiteral(name,
2989 RelocInfo::kNoPosition,
2990 DECLARATION,
2991 CHECK_OK);
Steve Block9fac8402011-05-12 15:51:54 +01002992 // Allow any number of parameters for compatiabilty with JSC.
2993 // Specification only allows zero parameters for get and one for set.
Ben Murdochbb769b22010-08-11 14:56:33 +01002994 ObjectLiteral::Property* property =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002995 new ObjectLiteral::Property(is_getter, value);
Ben Murdochbb769b22010-08-11 14:56:33 +01002996 return property;
2997 } else {
2998 ReportUnexpectedToken(next);
2999 *ok = false;
3000 return NULL;
3001 }
3002}
3003
3004
Steve Blocka7e24c12009-10-30 11:49:00 +00003005Expression* Parser::ParseObjectLiteral(bool* ok) {
3006 // ObjectLiteral ::
3007 // '{' (
Ben Murdochbb769b22010-08-11 14:56:33 +01003008 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3009 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
Steve Blocka7e24c12009-10-30 11:49:00 +00003010 // )*[','] '}'
3011
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003012 ZoneList<ObjectLiteral::Property*>* properties =
3013 new ZoneList<ObjectLiteral::Property*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003014 int number_of_boilerplate_properties = 0;
3015
3016 Expect(Token::LBRACE, CHECK_OK);
3017 while (peek() != Token::RBRACE) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003018 if (fni_ != NULL) fni_->Enter();
3019
Steve Blocka7e24c12009-10-30 11:49:00 +00003020 Literal* key = NULL;
Ben Murdochbb769b22010-08-11 14:56:33 +01003021 Token::Value next = peek();
3022 switch (next) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003023 case Token::IDENTIFIER: {
Steve Blocka7e24c12009-10-30 11:49:00 +00003024 bool is_getter = false;
3025 bool is_setter = false;
3026 Handle<String> id =
3027 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003028 if (fni_ != NULL) fni_->PushLiteralName(id);
3029
Ben Murdochbb769b22010-08-11 14:56:33 +01003030 if ((is_getter || is_setter) && peek() != Token::COLON) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003031 ObjectLiteral::Property* property =
Ben Murdochbb769b22010-08-11 14:56:33 +01003032 ParseObjectLiteralGetSet(is_getter, CHECK_OK);
3033 if (IsBoilerplateProperty(property)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003034 number_of_boilerplate_properties++;
Ben Murdochbb769b22010-08-11 14:56:33 +01003035 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003036 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003037 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003038
3039 if (fni_ != NULL) {
3040 fni_->Infer();
3041 fni_->Leave();
3042 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003043 continue; // restart the while
Steve Blocka7e24c12009-10-30 11:49:00 +00003044 }
Ben Murdochbb769b22010-08-11 14:56:33 +01003045 // Failed to parse as get/set property, so it's just a property
3046 // called "get" or "set".
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003047 key = new Literal(id);
Steve Blocka7e24c12009-10-30 11:49:00 +00003048 break;
3049 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003050 case Token::STRING: {
3051 Consume(Token::STRING);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003052 Handle<String> string = GetSymbol(CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003053 if (fni_ != NULL) fni_->PushLiteralName(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003054 uint32_t index;
Iain Merrick75681382010-08-19 15:07:18 +01003055 if (!string.is_null() && string->AsArrayIndex(&index)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003056 key = NewNumberLiteral(index);
Ben Murdochbb769b22010-08-11 14:56:33 +01003057 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00003058 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003059 key = new Literal(string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003060 break;
3061 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003062 case Token::NUMBER: {
3063 Consume(Token::NUMBER);
Steve Block9fac8402011-05-12 15:51:54 +01003064 ASSERT(scanner().is_literal_ascii());
3065 double value = StringToDouble(scanner().literal_ascii_string(),
3066 ALLOW_HEX | ALLOW_OCTALS);
Steve Blocka7e24c12009-10-30 11:49:00 +00003067 key = NewNumberLiteral(value);
3068 break;
3069 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003070 default:
Ben Murdochbb769b22010-08-11 14:56:33 +01003071 if (Token::IsKeyword(next)) {
3072 Consume(next);
Iain Merrick9ac36c92010-09-13 15:29:50 +01003073 Handle<String> string = GetSymbol(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003074 key = new Literal(string);
Ben Murdochbb769b22010-08-11 14:56:33 +01003075 } else {
3076 // Unexpected token.
3077 Token::Value next = Next();
3078 ReportUnexpectedToken(next);
3079 *ok = false;
3080 return NULL;
3081 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003082 }
3083
3084 Expect(Token::COLON, CHECK_OK);
3085 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
3086
3087 ObjectLiteral::Property* property =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003088 new ObjectLiteral::Property(key, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003089
3090 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
3091 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003092 properties->Add(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00003093
3094 // TODO(1240767): Consider allowing trailing comma.
3095 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003096
3097 if (fni_ != NULL) {
3098 fni_->Infer();
3099 fni_->Leave();
3100 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003101 }
3102 Expect(Token::RBRACE, CHECK_OK);
3103 // Computation of literal_index must happen before pre parse bailout.
3104 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
Steve Blocka7e24c12009-10-30 11:49:00 +00003105
3106 Handle<FixedArray> constant_properties =
3107 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED);
Leon Clarke4515c472010-02-03 11:58:03 +00003108
Steve Blocka7e24c12009-10-30 11:49:00 +00003109 bool is_simple = true;
Steve Block6ded16b2010-05-10 14:33:55 +01003110 bool fast_elements = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003111 int depth = 1;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003112 BuildObjectLiteralConstantProperties(properties,
Leon Clarke4515c472010-02-03 11:58:03 +00003113 constant_properties,
3114 &is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003115 &fast_elements,
Leon Clarke4515c472010-02-03 11:58:03 +00003116 &depth);
Steve Blocka7e24c12009-10-30 11:49:00 +00003117 return new ObjectLiteral(constant_properties,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003118 properties,
Steve Blocka7e24c12009-10-30 11:49:00 +00003119 literal_index,
3120 is_simple,
Steve Block6ded16b2010-05-10 14:33:55 +01003121 fast_elements,
Steve Blocka7e24c12009-10-30 11:49:00 +00003122 depth);
3123}
3124
3125
3126Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003127 if (!scanner().ScanRegExpPattern(seen_equal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003128 Next();
3129 ReportMessage("unterminated_regexp", Vector<const char*>::empty());
3130 *ok = false;
3131 return NULL;
3132 }
3133
3134 int literal_index = temp_scope_->NextMaterializedLiteralIndex();
3135
Steve Block9fac8402011-05-12 15:51:54 +01003136 Handle<String> js_pattern = NextLiteralString(TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003137 scanner().ScanRegExpFlags();
Steve Block9fac8402011-05-12 15:51:54 +01003138 Handle<String> js_flags = NextLiteralString(TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003139 Next();
3140
3141 return new RegExpLiteral(js_pattern, js_flags, literal_index);
3142}
3143
3144
3145ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
3146 // Arguments ::
3147 // '(' (AssignmentExpression)*[','] ')'
3148
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003149 ZoneList<Expression*>* result = new ZoneList<Expression*>(4);
Steve Blocka7e24c12009-10-30 11:49:00 +00003150 Expect(Token::LPAREN, CHECK_OK);
3151 bool done = (peek() == Token::RPAREN);
3152 while (!done) {
3153 Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003154 result->Add(argument);
Steve Blocka7e24c12009-10-30 11:49:00 +00003155 done = (peek() == Token::RPAREN);
3156 if (!done) Expect(Token::COMMA, CHECK_OK);
3157 }
3158 Expect(Token::RPAREN, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003159 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003160}
3161
3162
3163FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
3164 int function_token_position,
3165 FunctionLiteralType type,
3166 bool* ok) {
3167 // Function ::
3168 // '(' FormalParameterList? ')' '{' FunctionBody '}'
Steve Blocka7e24c12009-10-30 11:49:00 +00003169 bool is_named = !var_name.is_null();
3170
3171 // The name associated with this function. If it's a function expression,
3172 // this is the actual function name, otherwise this is the name of the
3173 // variable declared and initialized with the function (expression). In
3174 // that case, we don't have a function name (it's empty).
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003175 Handle<String> name = is_named ? var_name : Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003176 // The function name, if any.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003177 Handle<String> function_name = Factory::empty_symbol();
Steve Blocka7e24c12009-10-30 11:49:00 +00003178 if (is_named && (type == EXPRESSION || type == NESTED)) {
3179 function_name = name;
3180 }
3181
3182 int num_parameters = 0;
3183 // Parse function body.
Ben Murdochf87a2032010-10-22 12:50:53 +01003184 { Scope* scope =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003185 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
3186 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
3187 scope);
3188 TemporaryScope temp_scope(&this->temp_scope_);
Steve Blocka7e24c12009-10-30 11:49:00 +00003189 top_scope_->SetScopeName(name);
3190
3191 // FormalParameterList ::
3192 // '(' (Identifier)*[','] ')'
3193 Expect(Token::LPAREN, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003194 int start_pos = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003195 bool done = (peek() == Token::RPAREN);
3196 while (!done) {
3197 Handle<String> param_name = ParseIdentifier(CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003198 top_scope_->AddParameter(top_scope_->DeclareLocal(param_name,
3199 Variable::VAR));
3200 num_parameters++;
Steve Blocka7e24c12009-10-30 11:49:00 +00003201 done = (peek() == Token::RPAREN);
3202 if (!done) Expect(Token::COMMA, CHECK_OK);
3203 }
3204 Expect(Token::RPAREN, CHECK_OK);
3205
3206 Expect(Token::LBRACE, CHECK_OK);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003207 ZoneList<Statement*>* body = new ZoneList<Statement*>(8);
Steve Blocka7e24c12009-10-30 11:49:00 +00003208
3209 // If we have a named function expression, we add a local variable
3210 // declaration to the body of the function with the name of the
3211 // function and let it refer to the function itself (closure).
3212 // NOTE: We create a proxy and resolve it here so that in the
3213 // future we can change the AST to only refer to VariableProxies
3214 // instead of Variables and Proxis as is the case now.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003215 if (!function_name.is_null() && function_name->length() > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003216 Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
3217 VariableProxy* fproxy =
3218 top_scope_->NewUnresolved(function_name, inside_with());
3219 fproxy->BindTo(fvar);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003220 body->Add(new ExpressionStatement(
3221 new Assignment(Token::INIT_CONST, fproxy,
3222 new ThisFunction(),
3223 RelocInfo::kNoPosition)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003224 }
3225
3226 // Determine if the function will be lazily compiled. The mode can
3227 // only be PARSE_LAZILY if the --lazy flag is true.
3228 bool is_lazily_compiled =
3229 mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext();
3230
Ben Murdochb0fe1622011-05-05 13:52:32 +01003231 int function_block_pos = scanner().location().beg_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003232 int materialized_literal_count;
3233 int expected_property_count;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003234 int end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003235 bool only_simple_this_property_assignments;
3236 Handle<FixedArray> this_property_assignments;
3237 if (is_lazily_compiled && pre_data() != NULL) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003238 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos);
Leon Clarkeac952652010-07-15 11:15:24 +01003239 if (!entry.is_valid()) {
3240 ReportInvalidPreparseData(name, CHECK_OK);
3241 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003242 end_pos = entry.end_pos();
3243 if (end_pos <= function_block_pos) {
Leon Clarkeac952652010-07-15 11:15:24 +01003244 // End position greater than end of stream is safe, and hard to check.
3245 ReportInvalidPreparseData(name, CHECK_OK);
3246 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003247 Counters::total_preparse_skipped.Increment(end_pos - function_block_pos);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003248 // Seek to position just before terminal '}'.
3249 scanner().SeekForward(end_pos - 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00003250 materialized_literal_count = entry.literal_count();
3251 expected_property_count = entry.property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003252 only_simple_this_property_assignments = false;
3253 this_property_assignments = Factory::empty_fixed_array();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003254 Expect(Token::RBRACE, CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003255 } else {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003256 ParseSourceElements(body, Token::RBRACE, CHECK_OK);
3257
Steve Blocka7e24c12009-10-30 11:49:00 +00003258 materialized_literal_count = temp_scope.materialized_literal_count();
3259 expected_property_count = temp_scope.expected_property_count();
Steve Blocka7e24c12009-10-30 11:49:00 +00003260 only_simple_this_property_assignments =
3261 temp_scope.only_simple_this_property_assignments();
3262 this_property_assignments = temp_scope.this_property_assignments();
Steve Blocka7e24c12009-10-30 11:49:00 +00003263
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003264 Expect(Token::RBRACE, CHECK_OK);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003265 end_pos = scanner().location().end_pos;
Steve Blocka7e24c12009-10-30 11:49:00 +00003266 }
3267
3268 FunctionLiteral* function_literal =
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003269 new FunctionLiteral(name,
Steve Blocka7e24c12009-10-30 11:49:00 +00003270 top_scope_,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003271 body,
Steve Blocka7e24c12009-10-30 11:49:00 +00003272 materialized_literal_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003273 expected_property_count,
Steve Blocka7e24c12009-10-30 11:49:00 +00003274 only_simple_this_property_assignments,
3275 this_property_assignments,
3276 num_parameters,
3277 start_pos,
3278 end_pos,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003279 function_name->length() > 0,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003280 temp_scope.ContainsLoops());
3281 function_literal->set_function_token_position(function_token_position);
Steve Block6ded16b2010-05-10 14:33:55 +01003282
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003283 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal);
Steve Blocka7e24c12009-10-30 11:49:00 +00003284 return function_literal;
3285 }
3286}
3287
3288
3289Expression* Parser::ParseV8Intrinsic(bool* ok) {
3290 // CallRuntime ::
3291 // '%' Identifier Arguments
3292
3293 Expect(Token::MOD, CHECK_OK);
3294 Handle<String> name = ParseIdentifier(CHECK_OK);
Steve Blocka7e24c12009-10-30 11:49:00 +00003295 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003296
3297 if (extension_ != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003298 // The extension structures are only accessible while parsing the
3299 // very first time not when reparsing because of lazy compilation.
3300 top_scope_->ForceEagerCompilation();
3301 }
3302
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003303 Runtime::Function* function = Runtime::FunctionForSymbol(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00003304
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003305 // Check for built-in IS_VAR macro.
3306 if (function != NULL &&
3307 function->intrinsic_type == Runtime::RUNTIME &&
3308 function->function_id == Runtime::kIS_VAR) {
3309 // %IS_VAR(x) evaluates to x if x is a variable,
3310 // leads to a parse error otherwise. Could be implemented as an
3311 // inline function %_IS_VAR(x) to eliminate this special case.
3312 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
3313 return args->at(0);
3314 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +00003315 ReportMessage("unable_to_parse", Vector<const char*>::empty());
Steve Block6ded16b2010-05-10 14:33:55 +01003316 *ok = false;
3317 return NULL;
Steve Block6ded16b2010-05-10 14:33:55 +01003318 }
3319 }
3320
Kristian Monsen0d5e1162010-09-30 15:31:59 +01003321 // Check that the expected number of arguments are being passed.
3322 if (function != NULL &&
3323 function->nargs != -1 &&
3324 function->nargs != args->length()) {
3325 ReportMessage("illegal_access", Vector<const char*>::empty());
3326 *ok = false;
3327 return NULL;
3328 }
3329
3330 // We have a valid intrinsics call or a call to a builtin.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003331 return new CallRuntime(name, function, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00003332}
3333
3334
3335void Parser::Consume(Token::Value token) {
3336 Token::Value next = Next();
3337 USE(next);
3338 USE(token);
3339 ASSERT(next == token);
3340}
3341
3342
3343void Parser::Expect(Token::Value token, bool* ok) {
3344 Token::Value next = Next();
3345 if (next == token) return;
3346 ReportUnexpectedToken(next);
3347 *ok = false;
3348}
3349
3350
Leon Clarke4515c472010-02-03 11:58:03 +00003351bool Parser::Check(Token::Value token) {
3352 Token::Value next = peek();
3353 if (next == token) {
3354 Consume(next);
3355 return true;
3356 }
3357 return false;
3358}
3359
3360
Steve Blocka7e24c12009-10-30 11:49:00 +00003361void Parser::ExpectSemicolon(bool* ok) {
3362 // Check for automatic semicolon insertion according to
3363 // the rules given in ECMA-262, section 7.9, page 21.
3364 Token::Value tok = peek();
3365 if (tok == Token::SEMICOLON) {
3366 Next();
3367 return;
3368 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003369 if (scanner().has_line_terminator_before_next() ||
Steve Blocka7e24c12009-10-30 11:49:00 +00003370 tok == Token::RBRACE ||
3371 tok == Token::EOS) {
3372 return;
3373 }
3374 Expect(Token::SEMICOLON, ok);
3375}
3376
3377
3378Literal* Parser::GetLiteralUndefined() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003379 return new Literal(Factory::undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003380}
3381
3382
3383Literal* Parser::GetLiteralTheHole() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003384 return new Literal(Factory::the_hole_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003385}
3386
3387
3388Literal* Parser::GetLiteralNumber(double value) {
3389 return NewNumberLiteral(value);
3390}
3391
3392
3393Handle<String> Parser::ParseIdentifier(bool* ok) {
3394 Expect(Token::IDENTIFIER, ok);
3395 if (!*ok) return Handle<String>();
Iain Merrick9ac36c92010-09-13 15:29:50 +01003396 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003397}
3398
Ben Murdochbb769b22010-08-11 14:56:33 +01003399
3400Handle<String> Parser::ParseIdentifierName(bool* ok) {
3401 Token::Value next = Next();
3402 if (next != Token::IDENTIFIER && !Token::IsKeyword(next)) {
3403 ReportUnexpectedToken(next);
3404 *ok = false;
3405 return Handle<String>();
3406 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01003407 return GetSymbol(ok);
Ben Murdochbb769b22010-08-11 14:56:33 +01003408}
3409
3410
Steve Blocka7e24c12009-10-30 11:49:00 +00003411// This function reads an identifier and determines whether or not it
3412// is 'get' or 'set'. The reason for not using ParseIdentifier and
3413// checking on the output is that this involves heap allocation which
3414// we can't do during preparsing.
3415Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get,
3416 bool* is_set,
3417 bool* ok) {
3418 Expect(Token::IDENTIFIER, ok);
3419 if (!*ok) return Handle<String>();
Steve Block9fac8402011-05-12 15:51:54 +01003420 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
3421 const char* token = scanner().literal_ascii_string().start();
3422 *is_get = strncmp(token, "get", 3) == 0;
3423 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00003424 }
Iain Merrick9ac36c92010-09-13 15:29:50 +01003425 return GetSymbol(ok);
Steve Blocka7e24c12009-10-30 11:49:00 +00003426}
3427
3428
3429// ----------------------------------------------------------------------------
3430// Parser support
3431
3432
3433bool Parser::TargetStackContainsLabel(Handle<String> label) {
3434 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3435 BreakableStatement* stat = t->node()->AsBreakableStatement();
3436 if (stat != NULL && ContainsLabel(stat->labels(), label))
3437 return true;
3438 }
3439 return false;
3440}
3441
3442
3443BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
3444 bool anonymous = label.is_null();
3445 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3446 BreakableStatement* stat = t->node()->AsBreakableStatement();
3447 if (stat == NULL) continue;
3448 if ((anonymous && stat->is_target_for_anonymous()) ||
3449 (!anonymous && ContainsLabel(stat->labels(), label))) {
3450 RegisterTargetUse(stat->break_target(), t->previous());
3451 return stat;
3452 }
3453 }
3454 return NULL;
3455}
3456
3457
3458IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
3459 bool* ok) {
3460 bool anonymous = label.is_null();
3461 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3462 IterationStatement* stat = t->node()->AsIterationStatement();
3463 if (stat == NULL) continue;
3464
3465 ASSERT(stat->is_target_for_anonymous());
3466 if (anonymous || ContainsLabel(stat->labels(), label)) {
3467 RegisterTargetUse(stat->continue_target(), t->previous());
3468 return stat;
3469 }
3470 }
3471 return NULL;
3472}
3473
3474
3475void Parser::RegisterTargetUse(BreakTarget* target, Target* stop) {
3476 // Register that a break target found at the given stop in the
3477 // target stack has been used from the top of the target stack. Add
3478 // the break target to any TargetCollectors passed on the stack.
3479 for (Target* t = target_stack_; t != stop; t = t->previous()) {
3480 TargetCollector* collector = t->node()->AsTargetCollector();
3481 if (collector != NULL) collector->AddTarget(target);
3482 }
3483}
3484
3485
3486Literal* Parser::NewNumberLiteral(double number) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003487 return new Literal(Factory::NewNumber(number, TENURED));
Steve Blocka7e24c12009-10-30 11:49:00 +00003488}
3489
3490
3491Expression* Parser::NewThrowReferenceError(Handle<String> type) {
3492 return NewThrowError(Factory::MakeReferenceError_symbol(),
3493 type, HandleVector<Object>(NULL, 0));
3494}
3495
3496
3497Expression* Parser::NewThrowSyntaxError(Handle<String> type,
3498 Handle<Object> first) {
3499 int argc = first.is_null() ? 0 : 1;
3500 Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
3501 return NewThrowError(Factory::MakeSyntaxError_symbol(), type, arguments);
3502}
3503
3504
3505Expression* Parser::NewThrowTypeError(Handle<String> type,
3506 Handle<Object> first,
3507 Handle<Object> second) {
3508 ASSERT(!first.is_null() && !second.is_null());
3509 Handle<Object> elements[] = { first, second };
3510 Vector< Handle<Object> > arguments =
3511 HandleVector<Object>(elements, ARRAY_SIZE(elements));
3512 return NewThrowError(Factory::MakeTypeError_symbol(), type, arguments);
3513}
3514
3515
3516Expression* Parser::NewThrowError(Handle<String> constructor,
3517 Handle<String> type,
3518 Vector< Handle<Object> > arguments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003519 int argc = arguments.length();
3520 Handle<JSArray> array = Factory::NewJSArray(argc, TENURED);
3521 ASSERT(array->IsJSArray() && array->HasFastElements());
3522 for (int i = 0; i < argc; i++) {
3523 Handle<Object> element = arguments[i];
3524 if (!element.is_null()) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003525 // We know this doesn't cause a GC here because we allocated the JSArray
3526 // large enough.
John Reck59135872010-11-02 12:39:01 -07003527 array->SetFastElement(i, *element)->ToObjectUnchecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00003528 }
3529 }
3530 ZoneList<Expression*>* args = new ZoneList<Expression*>(2);
3531 args->Add(new Literal(type));
3532 args->Add(new Literal(array));
3533 return new Throw(new CallRuntime(constructor, NULL, args),
3534 scanner().location().beg_pos);
3535}
3536
Leon Clarke4515c472010-02-03 11:58:03 +00003537// ----------------------------------------------------------------------------
3538// JSON
3539
Ben Murdochb0fe1622011-05-05 13:52:32 +01003540Handle<Object> JsonParser::ParseJson(Handle<String> script,
3541 UC16CharacterStream* source) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08003542 scanner_.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003543 stack_overflow_ = false;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003544 Handle<Object> result = ParseJsonValue();
3545 if (result.is_null() || scanner_.Next() != Token::EOS) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003546 if (stack_overflow_) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003547 // Scanner failed.
3548 Top::StackOverflow();
3549 } else {
3550 // Parse failed. Scanner's current token is the unexpected token.
3551 Token::Value token = scanner_.current_token();
3552
3553 const char* message;
3554 const char* name_opt = NULL;
3555
3556 switch (token) {
3557 case Token::EOS:
3558 message = "unexpected_eos";
3559 break;
3560 case Token::NUMBER:
3561 message = "unexpected_token_number";
3562 break;
3563 case Token::STRING:
3564 message = "unexpected_token_string";
3565 break;
3566 case Token::IDENTIFIER:
3567 message = "unexpected_token_identifier";
3568 break;
3569 default:
3570 message = "unexpected_token";
3571 name_opt = Token::String(token);
3572 ASSERT(name_opt != NULL);
3573 break;
3574 }
3575
3576 Scanner::Location source_location = scanner_.location();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003577 MessageLocation location(Factory::NewScript(script),
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003578 source_location.beg_pos,
3579 source_location.end_pos);
3580 int argc = (name_opt == NULL) ? 0 : 1;
3581 Handle<JSArray> array = Factory::NewJSArray(argc);
3582 if (name_opt != NULL) {
3583 SetElement(array,
3584 0,
3585 Factory::NewStringFromUtf8(CStrVector(name_opt)));
3586 }
3587 Handle<Object> result = Factory::NewSyntaxError(message, array);
3588 Top::Throw(*result, &location);
3589 return Handle<Object>::null();
3590 }
3591 }
Leon Clarke4515c472010-02-03 11:58:03 +00003592 return result;
3593}
3594
3595
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003596Handle<String> JsonParser::GetString() {
3597 int literal_length = scanner_.literal_length();
3598 if (literal_length == 0) {
3599 return Factory::empty_string();
3600 }
Steve Block9fac8402011-05-12 15:51:54 +01003601 if (scanner_.is_literal_ascii()) {
3602 return Factory::NewStringFromAscii(scanner_.literal_ascii_string());
3603 } else {
3604 return Factory::NewStringFromTwoByte(scanner_.literal_uc16_string());
3605 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003606}
3607
3608
Leon Clarke4515c472010-02-03 11:58:03 +00003609// Parse any JSON value.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003610Handle<Object> JsonParser::ParseJsonValue() {
3611 Token::Value token = scanner_.Next();
Leon Clarke4515c472010-02-03 11:58:03 +00003612 switch (token) {
3613 case Token::STRING: {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003614 return GetString();
Leon Clarke4515c472010-02-03 11:58:03 +00003615 }
3616 case Token::NUMBER: {
Steve Block9fac8402011-05-12 15:51:54 +01003617 ASSERT(scanner_.is_literal_ascii());
3618 double value = StringToDouble(scanner_.literal_ascii_string(),
Leon Clarke4515c472010-02-03 11:58:03 +00003619 NO_FLAGS, // Hex, octal or trailing junk.
3620 OS::nan_value());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003621 return Factory::NewNumber(value);
Leon Clarke4515c472010-02-03 11:58:03 +00003622 }
3623 case Token::FALSE_LITERAL:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003624 return Factory::false_value();
Leon Clarke4515c472010-02-03 11:58:03 +00003625 case Token::TRUE_LITERAL:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003626 return Factory::true_value();
Leon Clarke4515c472010-02-03 11:58:03 +00003627 case Token::NULL_LITERAL:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003628 return Factory::null_value();
3629 case Token::LBRACE:
3630 return ParseJsonObject();
3631 case Token::LBRACK:
3632 return ParseJsonArray();
Leon Clarke4515c472010-02-03 11:58:03 +00003633 default:
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003634 return ReportUnexpectedToken();
Leon Clarke4515c472010-02-03 11:58:03 +00003635 }
3636}
3637
3638
3639// Parse a JSON object. Scanner must be right after '{' token.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003640Handle<Object> JsonParser::ParseJsonObject() {
3641 Handle<JSFunction> object_constructor(
3642 Top::global_context()->object_function());
3643 Handle<JSObject> json_object = Factory::NewJSObject(object_constructor);
3644 if (scanner_.peek() == Token::RBRACE) {
3645 scanner_.Next();
3646 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003647 if (StackLimitCheck().HasOverflowed()) {
3648 stack_overflow_ = true;
3649 return Handle<Object>::null();
3650 }
Leon Clarke4515c472010-02-03 11:58:03 +00003651 do {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003652 if (scanner_.Next() != Token::STRING) {
3653 return ReportUnexpectedToken();
3654 }
3655 Handle<String> key = GetString();
3656 if (scanner_.Next() != Token::COLON) {
3657 return ReportUnexpectedToken();
3658 }
3659 Handle<Object> value = ParseJsonValue();
3660 if (value.is_null()) return Handle<Object>::null();
Leon Clarke4515c472010-02-03 11:58:03 +00003661 uint32_t index;
3662 if (key->AsArrayIndex(&index)) {
Ben Murdoch086aeea2011-05-13 15:57:08 +01003663 SetOwnElement(json_object, index, value);
Leon Clarke4515c472010-02-03 11:58:03 +00003664 } else {
Ben Murdoch086aeea2011-05-13 15:57:08 +01003665 SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE);
Leon Clarke4515c472010-02-03 11:58:03 +00003666 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003667 } while (scanner_.Next() == Token::COMMA);
3668 if (scanner_.current_token() != Token::RBRACE) {
3669 return ReportUnexpectedToken();
3670 }
Leon Clarke4515c472010-02-03 11:58:03 +00003671 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003672 return json_object;
Leon Clarke4515c472010-02-03 11:58:03 +00003673}
3674
3675
3676// Parse a JSON array. Scanner must be right after '[' token.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003677Handle<Object> JsonParser::ParseJsonArray() {
3678 ZoneScope zone_scope(DELETE_ON_EXIT);
3679 ZoneList<Handle<Object> > elements(4);
Leon Clarke4515c472010-02-03 11:58:03 +00003680
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003681 Token::Value token = scanner_.peek();
3682 if (token == Token::RBRACK) {
3683 scanner_.Next();
3684 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003685 if (StackLimitCheck().HasOverflowed()) {
3686 stack_overflow_ = true;
3687 return Handle<Object>::null();
3688 }
Leon Clarke4515c472010-02-03 11:58:03 +00003689 do {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003690 Handle<Object> element = ParseJsonValue();
3691 if (element.is_null()) return Handle<Object>::null();
3692 elements.Add(element);
3693 token = scanner_.Next();
3694 } while (token == Token::COMMA);
3695 if (token != Token::RBRACK) {
3696 return ReportUnexpectedToken();
3697 }
Leon Clarke4515c472010-02-03 11:58:03 +00003698 }
Leon Clarke4515c472010-02-03 11:58:03 +00003699
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003700 // Allocate a fixed array with all the elements.
3701 Handle<FixedArray> fast_elements =
3702 Factory::NewFixedArray(elements.length());
Leon Clarke4515c472010-02-03 11:58:03 +00003703
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003704 for (int i = 0, n = elements.length(); i < n; i++) {
3705 fast_elements->set(i, *elements[i]);
3706 }
Leon Clarke4515c472010-02-03 11:58:03 +00003707
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003708 return Factory::NewJSArrayWithElements(fast_elements);
Leon Clarke4515c472010-02-03 11:58:03 +00003709}
3710
Steve Blocka7e24c12009-10-30 11:49:00 +00003711// ----------------------------------------------------------------------------
3712// Regular expressions
3713
3714
3715RegExpParser::RegExpParser(FlatStringReader* in,
3716 Handle<String>* error,
3717 bool multiline)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003718 : error_(error),
3719 captures_(NULL),
3720 in_(in),
3721 current_(kEndMarker),
3722 next_pos_(0),
3723 capture_count_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +00003724 has_more_(true),
3725 multiline_(multiline),
Steve Blocka7e24c12009-10-30 11:49:00 +00003726 simple_(false),
3727 contains_anchor_(false),
Steve Blocka7e24c12009-10-30 11:49:00 +00003728 is_scanned_for_captures_(false),
Steve Blocka7e24c12009-10-30 11:49:00 +00003729 failed_(false) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003730 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00003731}
3732
3733
3734uc32 RegExpParser::Next() {
3735 if (has_next()) {
3736 return in()->Get(next_pos_);
3737 } else {
3738 return kEndMarker;
3739 }
3740}
3741
3742
3743void RegExpParser::Advance() {
3744 if (next_pos_ < in()->length()) {
3745 StackLimitCheck check;
3746 if (check.HasOverflowed()) {
3747 ReportError(CStrVector(Top::kStackOverflowMessage));
3748 } else if (Zone::excess_allocation()) {
3749 ReportError(CStrVector("Regular expression too large"));
3750 } else {
3751 current_ = in()->Get(next_pos_);
3752 next_pos_++;
3753 }
3754 } else {
3755 current_ = kEndMarker;
3756 has_more_ = false;
3757 }
3758}
3759
3760
3761void RegExpParser::Reset(int pos) {
3762 next_pos_ = pos;
3763 Advance();
3764}
3765
3766
3767void RegExpParser::Advance(int dist) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01003768 next_pos_ += dist - 1;
3769 Advance();
Steve Blocka7e24c12009-10-30 11:49:00 +00003770}
3771
3772
3773bool RegExpParser::simple() {
3774 return simple_;
3775}
3776
3777RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
3778 failed_ = true;
3779 *error_ = Factory::NewStringFromAscii(message, NOT_TENURED);
3780 // Zip to the end to make sure the no more input is read.
3781 current_ = kEndMarker;
3782 next_pos_ = in()->length();
3783 return NULL;
3784}
3785
3786
3787// Pattern ::
3788// Disjunction
3789RegExpTree* RegExpParser::ParsePattern() {
3790 RegExpTree* result = ParseDisjunction(CHECK_FAILED);
3791 ASSERT(!has_more());
3792 // If the result of parsing is a literal string atom, and it has the
3793 // same length as the input, then the atom is identical to the input.
3794 if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
3795 simple_ = true;
3796 }
3797 return result;
3798}
3799
3800
3801// Disjunction ::
3802// Alternative
3803// Alternative | Disjunction
3804// Alternative ::
3805// [empty]
3806// Term Alternative
3807// Term ::
3808// Assertion
3809// Atom
3810// Atom Quantifier
3811RegExpTree* RegExpParser::ParseDisjunction() {
3812 // Used to store current state while parsing subexpressions.
3813 RegExpParserState initial_state(NULL, INITIAL, 0);
3814 RegExpParserState* stored_state = &initial_state;
3815 // Cache the builder in a local variable for quick access.
3816 RegExpBuilder* builder = initial_state.builder();
3817 while (true) {
3818 switch (current()) {
3819 case kEndMarker:
3820 if (stored_state->IsSubexpression()) {
3821 // Inside a parenthesized group when hitting end of input.
3822 ReportError(CStrVector("Unterminated group") CHECK_FAILED);
3823 }
3824 ASSERT_EQ(INITIAL, stored_state->group_type());
3825 // Parsing completed successfully.
3826 return builder->ToRegExp();
3827 case ')': {
3828 if (!stored_state->IsSubexpression()) {
3829 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
3830 }
3831 ASSERT_NE(INITIAL, stored_state->group_type());
3832
3833 Advance();
3834 // End disjunction parsing and convert builder content to new single
3835 // regexp atom.
3836 RegExpTree* body = builder->ToRegExp();
3837
3838 int end_capture_index = captures_started();
3839
3840 int capture_index = stored_state->capture_index();
3841 SubexpressionType type = stored_state->group_type();
3842
3843 // Restore previous state.
3844 stored_state = stored_state->previous_state();
3845 builder = stored_state->builder();
3846
3847 // Build result of subexpression.
3848 if (type == CAPTURE) {
3849 RegExpCapture* capture = new RegExpCapture(body, capture_index);
3850 captures_->at(capture_index - 1) = capture;
3851 body = capture;
3852 } else if (type != GROUPING) {
3853 ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
3854 bool is_positive = (type == POSITIVE_LOOKAHEAD);
3855 body = new RegExpLookahead(body,
3856 is_positive,
3857 end_capture_index - capture_index,
3858 capture_index);
3859 }
3860 builder->AddAtom(body);
3861 break;
3862 }
3863 case '|': {
3864 Advance();
3865 builder->NewAlternative();
3866 continue;
3867 }
3868 case '*':
3869 case '+':
3870 case '?':
3871 return ReportError(CStrVector("Nothing to repeat"));
3872 case '^': {
3873 Advance();
3874 if (multiline_) {
3875 builder->AddAssertion(
3876 new RegExpAssertion(RegExpAssertion::START_OF_LINE));
3877 } else {
3878 builder->AddAssertion(
3879 new RegExpAssertion(RegExpAssertion::START_OF_INPUT));
3880 set_contains_anchor();
3881 }
3882 continue;
3883 }
3884 case '$': {
3885 Advance();
3886 RegExpAssertion::Type type =
3887 multiline_ ? RegExpAssertion::END_OF_LINE :
3888 RegExpAssertion::END_OF_INPUT;
3889 builder->AddAssertion(new RegExpAssertion(type));
3890 continue;
3891 }
3892 case '.': {
3893 Advance();
3894 // everything except \x0a, \x0d, \u2028 and \u2029
3895 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
3896 CharacterRange::AddClassEscape('.', ranges);
3897 RegExpTree* atom = new RegExpCharacterClass(ranges, false);
3898 builder->AddAtom(atom);
3899 break;
3900 }
3901 case '(': {
3902 SubexpressionType type = CAPTURE;
3903 Advance();
3904 if (current() == '?') {
3905 switch (Next()) {
3906 case ':':
3907 type = GROUPING;
3908 break;
3909 case '=':
3910 type = POSITIVE_LOOKAHEAD;
3911 break;
3912 case '!':
3913 type = NEGATIVE_LOOKAHEAD;
3914 break;
3915 default:
3916 ReportError(CStrVector("Invalid group") CHECK_FAILED);
3917 break;
3918 }
3919 Advance(2);
3920 } else {
3921 if (captures_ == NULL) {
3922 captures_ = new ZoneList<RegExpCapture*>(2);
3923 }
3924 if (captures_started() >= kMaxCaptures) {
3925 ReportError(CStrVector("Too many captures") CHECK_FAILED);
3926 }
3927 captures_->Add(NULL);
3928 }
3929 // Store current state and begin new disjunction parsing.
3930 stored_state = new RegExpParserState(stored_state,
3931 type,
3932 captures_started());
3933 builder = stored_state->builder();
3934 break;
3935 }
3936 case '[': {
3937 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
3938 builder->AddAtom(atom);
3939 break;
3940 }
3941 // Atom ::
3942 // \ AtomEscape
3943 case '\\':
3944 switch (Next()) {
3945 case kEndMarker:
3946 return ReportError(CStrVector("\\ at end of pattern"));
3947 case 'b':
3948 Advance(2);
3949 builder->AddAssertion(
3950 new RegExpAssertion(RegExpAssertion::BOUNDARY));
3951 continue;
3952 case 'B':
3953 Advance(2);
3954 builder->AddAssertion(
3955 new RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
3956 continue;
3957 // AtomEscape ::
3958 // CharacterClassEscape
3959 //
3960 // CharacterClassEscape :: one of
3961 // d D s S w W
3962 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
3963 uc32 c = Next();
3964 Advance(2);
3965 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
3966 CharacterRange::AddClassEscape(c, ranges);
3967 RegExpTree* atom = new RegExpCharacterClass(ranges, false);
3968 builder->AddAtom(atom);
3969 break;
3970 }
3971 case '1': case '2': case '3': case '4': case '5': case '6':
3972 case '7': case '8': case '9': {
3973 int index = 0;
3974 if (ParseBackReferenceIndex(&index)) {
3975 RegExpCapture* capture = NULL;
3976 if (captures_ != NULL && index <= captures_->length()) {
3977 capture = captures_->at(index - 1);
3978 }
3979 if (capture == NULL) {
3980 builder->AddEmpty();
3981 break;
3982 }
3983 RegExpTree* atom = new RegExpBackReference(capture);
3984 builder->AddAtom(atom);
3985 break;
3986 }
3987 uc32 first_digit = Next();
3988 if (first_digit == '8' || first_digit == '9') {
3989 // Treat as identity escape
3990 builder->AddCharacter(first_digit);
3991 Advance(2);
3992 break;
3993 }
3994 }
3995 // FALLTHROUGH
3996 case '0': {
3997 Advance();
3998 uc32 octal = ParseOctalLiteral();
3999 builder->AddCharacter(octal);
4000 break;
4001 }
4002 // ControlEscape :: one of
4003 // f n r t v
4004 case 'f':
4005 Advance(2);
4006 builder->AddCharacter('\f');
4007 break;
4008 case 'n':
4009 Advance(2);
4010 builder->AddCharacter('\n');
4011 break;
4012 case 'r':
4013 Advance(2);
4014 builder->AddCharacter('\r');
4015 break;
4016 case 't':
4017 Advance(2);
4018 builder->AddCharacter('\t');
4019 break;
4020 case 'v':
4021 Advance(2);
4022 builder->AddCharacter('\v');
4023 break;
4024 case 'c': {
Ben Murdoch086aeea2011-05-13 15:57:08 +01004025 Advance();
4026 uc32 controlLetter = Next();
4027 // Special case if it is an ASCII letter.
4028 // Convert lower case letters to uppercase.
4029 uc32 letter = controlLetter & ~('a' ^ 'A');
4030 if (letter < 'A' || 'Z' < letter) {
4031 // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
4032 // This is outside the specification. We match JSC in
4033 // reading the backslash as a literal character instead
4034 // of as starting an escape.
4035 builder->AddCharacter('\\');
4036 } else {
4037 Advance(2);
4038 builder->AddCharacter(controlLetter & 0x1f);
4039 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004040 break;
4041 }
4042 case 'x': {
4043 Advance(2);
4044 uc32 value;
4045 if (ParseHexEscape(2, &value)) {
4046 builder->AddCharacter(value);
4047 } else {
4048 builder->AddCharacter('x');
4049 }
4050 break;
4051 }
4052 case 'u': {
4053 Advance(2);
4054 uc32 value;
4055 if (ParseHexEscape(4, &value)) {
4056 builder->AddCharacter(value);
4057 } else {
4058 builder->AddCharacter('u');
4059 }
4060 break;
4061 }
4062 default:
4063 // Identity escape.
4064 builder->AddCharacter(Next());
4065 Advance(2);
4066 break;
4067 }
4068 break;
4069 case '{': {
4070 int dummy;
4071 if (ParseIntervalQuantifier(&dummy, &dummy)) {
4072 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
4073 }
4074 // fallthrough
4075 }
4076 default:
4077 builder->AddCharacter(current());
4078 Advance();
4079 break;
4080 } // end switch(current())
4081
4082 int min;
4083 int max;
4084 switch (current()) {
4085 // QuantifierPrefix ::
4086 // *
4087 // +
4088 // ?
4089 // {
4090 case '*':
4091 min = 0;
4092 max = RegExpTree::kInfinity;
4093 Advance();
4094 break;
4095 case '+':
4096 min = 1;
4097 max = RegExpTree::kInfinity;
4098 Advance();
4099 break;
4100 case '?':
4101 min = 0;
4102 max = 1;
4103 Advance();
4104 break;
4105 case '{':
4106 if (ParseIntervalQuantifier(&min, &max)) {
4107 if (max < min) {
4108 ReportError(CStrVector("numbers out of order in {} quantifier.")
4109 CHECK_FAILED);
4110 }
4111 break;
4112 } else {
4113 continue;
4114 }
4115 default:
4116 continue;
4117 }
Leon Clarkee46be812010-01-19 14:06:41 +00004118 RegExpQuantifier::Type type = RegExpQuantifier::GREEDY;
Steve Blocka7e24c12009-10-30 11:49:00 +00004119 if (current() == '?') {
Leon Clarkee46be812010-01-19 14:06:41 +00004120 type = RegExpQuantifier::NON_GREEDY;
4121 Advance();
4122 } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
4123 // FLAG_regexp_possessive_quantifier is a debug-only flag.
4124 type = RegExpQuantifier::POSSESSIVE;
Steve Blocka7e24c12009-10-30 11:49:00 +00004125 Advance();
4126 }
Leon Clarkee46be812010-01-19 14:06:41 +00004127 builder->AddQuantifierToAtom(min, max, type);
Steve Blocka7e24c12009-10-30 11:49:00 +00004128 }
4129}
4130
4131class SourceCharacter {
4132 public:
4133 static bool Is(uc32 c) {
4134 switch (c) {
4135 // case ']': case '}':
4136 // In spidermonkey and jsc these are treated as source characters
4137 // so we do too.
4138 case '^': case '$': case '\\': case '.': case '*': case '+':
4139 case '?': case '(': case ')': case '[': case '{': case '|':
4140 case RegExpParser::kEndMarker:
4141 return false;
4142 default:
4143 return true;
4144 }
4145 }
4146};
4147
4148
4149static unibrow::Predicate<SourceCharacter> source_character;
4150
4151
4152static inline bool IsSourceCharacter(uc32 c) {
4153 return source_character.get(c);
4154}
4155
4156#ifdef DEBUG
4157// Currently only used in an ASSERT.
4158static bool IsSpecialClassEscape(uc32 c) {
4159 switch (c) {
4160 case 'd': case 'D':
4161 case 's': case 'S':
4162 case 'w': case 'W':
4163 return true;
4164 default:
4165 return false;
4166 }
4167}
4168#endif
4169
4170
4171// In order to know whether an escape is a backreference or not we have to scan
4172// the entire regexp and find the number of capturing parentheses. However we
4173// don't want to scan the regexp twice unless it is necessary. This mini-parser
4174// is called when needed. It can see the difference between capturing and
4175// noncapturing parentheses and can skip character classes and backslash-escaped
4176// characters.
4177void RegExpParser::ScanForCaptures() {
4178 // Start with captures started previous to current position
4179 int capture_count = captures_started();
4180 // Add count of captures after this position.
4181 int n;
4182 while ((n = current()) != kEndMarker) {
4183 Advance();
4184 switch (n) {
4185 case '\\':
4186 Advance();
4187 break;
4188 case '[': {
4189 int c;
4190 while ((c = current()) != kEndMarker) {
4191 Advance();
4192 if (c == '\\') {
4193 Advance();
4194 } else {
4195 if (c == ']') break;
4196 }
4197 }
4198 break;
4199 }
4200 case '(':
4201 if (current() != '?') capture_count++;
4202 break;
4203 }
4204 }
4205 capture_count_ = capture_count;
4206 is_scanned_for_captures_ = true;
4207}
4208
4209
4210bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
4211 ASSERT_EQ('\\', current());
4212 ASSERT('1' <= Next() && Next() <= '9');
4213 // Try to parse a decimal literal that is no greater than the total number
4214 // of left capturing parentheses in the input.
4215 int start = position();
4216 int value = Next() - '0';
4217 Advance(2);
4218 while (true) {
4219 uc32 c = current();
4220 if (IsDecimalDigit(c)) {
4221 value = 10 * value + (c - '0');
4222 if (value > kMaxCaptures) {
4223 Reset(start);
4224 return false;
4225 }
4226 Advance();
4227 } else {
4228 break;
4229 }
4230 }
4231 if (value > captures_started()) {
4232 if (!is_scanned_for_captures_) {
4233 int saved_position = position();
4234 ScanForCaptures();
4235 Reset(saved_position);
4236 }
4237 if (value > capture_count_) {
4238 Reset(start);
4239 return false;
4240 }
4241 }
4242 *index_out = value;
4243 return true;
4244}
4245
4246
4247// QuantifierPrefix ::
4248// { DecimalDigits }
4249// { DecimalDigits , }
4250// { DecimalDigits , DecimalDigits }
4251//
4252// Returns true if parsing succeeds, and set the min_out and max_out
4253// values. Values are truncated to RegExpTree::kInfinity if they overflow.
4254bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
4255 ASSERT_EQ(current(), '{');
4256 int start = position();
4257 Advance();
4258 int min = 0;
4259 if (!IsDecimalDigit(current())) {
4260 Reset(start);
4261 return false;
4262 }
4263 while (IsDecimalDigit(current())) {
4264 int next = current() - '0';
4265 if (min > (RegExpTree::kInfinity - next) / 10) {
4266 // Overflow. Skip past remaining decimal digits and return -1.
4267 do {
4268 Advance();
4269 } while (IsDecimalDigit(current()));
4270 min = RegExpTree::kInfinity;
4271 break;
4272 }
4273 min = 10 * min + next;
4274 Advance();
4275 }
4276 int max = 0;
4277 if (current() == '}') {
4278 max = min;
4279 Advance();
4280 } else if (current() == ',') {
4281 Advance();
4282 if (current() == '}') {
4283 max = RegExpTree::kInfinity;
4284 Advance();
4285 } else {
4286 while (IsDecimalDigit(current())) {
4287 int next = current() - '0';
4288 if (max > (RegExpTree::kInfinity - next) / 10) {
4289 do {
4290 Advance();
4291 } while (IsDecimalDigit(current()));
4292 max = RegExpTree::kInfinity;
4293 break;
4294 }
4295 max = 10 * max + next;
4296 Advance();
4297 }
4298 if (current() != '}') {
4299 Reset(start);
4300 return false;
4301 }
4302 Advance();
4303 }
4304 } else {
4305 Reset(start);
4306 return false;
4307 }
4308 *min_out = min;
4309 *max_out = max;
4310 return true;
4311}
4312
4313
Steve Blocka7e24c12009-10-30 11:49:00 +00004314uc32 RegExpParser::ParseOctalLiteral() {
4315 ASSERT('0' <= current() && current() <= '7');
4316 // For compatibility with some other browsers (not all), we parse
4317 // up to three octal digits with a value below 256.
4318 uc32 value = current() - '0';
4319 Advance();
4320 if ('0' <= current() && current() <= '7') {
4321 value = value * 8 + current() - '0';
4322 Advance();
4323 if (value < 32 && '0' <= current() && current() <= '7') {
4324 value = value * 8 + current() - '0';
4325 Advance();
4326 }
4327 }
4328 return value;
4329}
4330
4331
4332bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
4333 int start = position();
4334 uc32 val = 0;
4335 bool done = false;
4336 for (int i = 0; !done; i++) {
4337 uc32 c = current();
4338 int d = HexValue(c);
4339 if (d < 0) {
4340 Reset(start);
4341 return false;
4342 }
4343 val = val * 16 + d;
4344 Advance();
4345 if (i == length - 1) {
4346 done = true;
4347 }
4348 }
4349 *value = val;
4350 return true;
4351}
4352
4353
4354uc32 RegExpParser::ParseClassCharacterEscape() {
4355 ASSERT(current() == '\\');
4356 ASSERT(has_next() && !IsSpecialClassEscape(Next()));
4357 Advance();
4358 switch (current()) {
4359 case 'b':
4360 Advance();
4361 return '\b';
4362 // ControlEscape :: one of
4363 // f n r t v
4364 case 'f':
4365 Advance();
4366 return '\f';
4367 case 'n':
4368 Advance();
4369 return '\n';
4370 case 'r':
4371 Advance();
4372 return '\r';
4373 case 't':
4374 Advance();
4375 return '\t';
4376 case 'v':
4377 Advance();
4378 return '\v';
Ben Murdoch086aeea2011-05-13 15:57:08 +01004379 case 'c': {
4380 uc32 controlLetter = Next();
4381 uc32 letter = controlLetter & ~('A' ^ 'a');
4382 // For compatibility with JSC, inside a character class
4383 // we also accept digits and underscore as control characters.
4384 if ((controlLetter >= '0' && controlLetter <= '9') ||
4385 controlLetter == '_' ||
4386 (letter >= 'A' && letter <= 'Z')) {
4387 Advance(2);
4388 // Control letters mapped to ASCII control characters in the range
4389 // 0x00-0x1f.
4390 return controlLetter & 0x1f;
4391 }
4392 // We match JSC in reading the backslash as a literal
4393 // character instead of as starting an escape.
4394 return '\\';
4395 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004396 case '0': case '1': case '2': case '3': case '4': case '5':
4397 case '6': case '7':
4398 // For compatibility, we interpret a decimal escape that isn't
4399 // a back reference (and therefore either \0 or not valid according
4400 // to the specification) as a 1..3 digit octal character code.
4401 return ParseOctalLiteral();
4402 case 'x': {
4403 Advance();
4404 uc32 value;
4405 if (ParseHexEscape(2, &value)) {
4406 return value;
4407 }
4408 // If \x is not followed by a two-digit hexadecimal, treat it
4409 // as an identity escape.
4410 return 'x';
4411 }
4412 case 'u': {
4413 Advance();
4414 uc32 value;
4415 if (ParseHexEscape(4, &value)) {
4416 return value;
4417 }
4418 // If \u is not followed by a four-digit hexadecimal, treat it
4419 // as an identity escape.
4420 return 'u';
4421 }
4422 default: {
4423 // Extended identity escape. We accept any character that hasn't
4424 // been matched by a more specific case, not just the subset required
4425 // by the ECMAScript specification.
4426 uc32 result = current();
4427 Advance();
4428 return result;
4429 }
4430 }
4431 return 0;
4432}
4433
4434
4435CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4436 ASSERT_EQ(0, *char_class);
4437 uc32 first = current();
4438 if (first == '\\') {
4439 switch (Next()) {
4440 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4441 *char_class = Next();
4442 Advance(2);
4443 return CharacterRange::Singleton(0); // Return dummy value.
4444 }
4445 case kEndMarker:
4446 return ReportError(CStrVector("\\ at end of pattern"));
4447 default:
4448 uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4449 return CharacterRange::Singleton(c);
4450 }
4451 } else {
4452 Advance();
4453 return CharacterRange::Singleton(first);
4454 }
4455}
4456
4457
Ben Murdochb0fe1622011-05-05 13:52:32 +01004458static const uc16 kNoCharClass = 0;
4459
4460// Adds range or pre-defined character class to character ranges.
4461// If char_class is not kInvalidClass, it's interpreted as a class
4462// escape (i.e., 's' means whitespace, from '\s').
4463static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
4464 uc16 char_class,
4465 CharacterRange range) {
4466 if (char_class != kNoCharClass) {
4467 CharacterRange::AddClassEscape(char_class, ranges);
4468 } else {
4469 ranges->Add(range);
4470 }
4471}
4472
4473
Steve Blocka7e24c12009-10-30 11:49:00 +00004474RegExpTree* RegExpParser::ParseCharacterClass() {
4475 static const char* kUnterminated = "Unterminated character class";
4476 static const char* kRangeOutOfOrder = "Range out of order in character class";
4477
4478 ASSERT_EQ(current(), '[');
4479 Advance();
4480 bool is_negated = false;
4481 if (current() == '^') {
4482 is_negated = true;
4483 Advance();
4484 }
4485 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4486 while (has_more() && current() != ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004487 uc16 char_class = kNoCharClass;
Steve Blocka7e24c12009-10-30 11:49:00 +00004488 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
Steve Blocka7e24c12009-10-30 11:49:00 +00004489 if (current() == '-') {
4490 Advance();
4491 if (current() == kEndMarker) {
4492 // If we reach the end we break out of the loop and let the
4493 // following code report an error.
4494 break;
4495 } else if (current() == ']') {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004496 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004497 ranges->Add(CharacterRange::Singleton('-'));
4498 break;
4499 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01004500 uc16 char_class_2 = kNoCharClass;
4501 CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
4502 if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
4503 // Either end is an escaped character class. Treat the '-' verbatim.
4504 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004505 ranges->Add(CharacterRange::Singleton('-'));
Ben Murdochb0fe1622011-05-05 13:52:32 +01004506 AddRangeOrEscape(ranges, char_class_2, next);
Steve Blocka7e24c12009-10-30 11:49:00 +00004507 continue;
4508 }
4509 if (first.from() > next.to()) {
4510 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
4511 }
4512 ranges->Add(CharacterRange::Range(first.from(), next.to()));
4513 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +01004514 AddRangeOrEscape(ranges, char_class, first);
Steve Blocka7e24c12009-10-30 11:49:00 +00004515 }
4516 }
4517 if (!has_more()) {
4518 return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
4519 }
4520 Advance();
4521 if (ranges->length() == 0) {
4522 ranges->Add(CharacterRange::Everything());
4523 is_negated = !is_negated;
4524 }
4525 return new RegExpCharacterClass(ranges, is_negated);
4526}
4527
4528
4529// ----------------------------------------------------------------------------
4530// The Parser interface.
4531
Steve Blocka7e24c12009-10-30 11:49:00 +00004532ParserMessage::~ParserMessage() {
4533 for (int i = 0; i < args().length(); i++)
4534 DeleteArray(args()[i]);
4535 DeleteArray(args().start());
4536}
4537
4538
4539ScriptDataImpl::~ScriptDataImpl() {
Iain Merrick9ac36c92010-09-13 15:29:50 +01004540 if (owns_store_) store_.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00004541}
4542
4543
4544int ScriptDataImpl::Length() {
Leon Clarkef7060e22010-06-03 12:02:55 +01004545 return store_.length() * sizeof(unsigned);
Steve Blocka7e24c12009-10-30 11:49:00 +00004546}
4547
4548
Leon Clarkef7060e22010-06-03 12:02:55 +01004549const char* ScriptDataImpl::Data() {
4550 return reinterpret_cast<const char*>(store_.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00004551}
4552
4553
Leon Clarkee46be812010-01-19 14:06:41 +00004554bool ScriptDataImpl::HasError() {
4555 return has_error();
4556}
4557
4558
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004559void ScriptDataImpl::Initialize() {
4560 // Prepares state for use.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004561 if (store_.length() >= PreparseDataConstants::kHeaderSize) {
4562 function_index_ = PreparseDataConstants::kHeaderSize;
4563 int symbol_data_offset = PreparseDataConstants::kHeaderSize
4564 + store_[PreparseDataConstants::kFunctionsSizeOffset];
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004565 if (store_.length() > symbol_data_offset) {
4566 symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
4567 } else {
4568 // Partial preparse causes no symbol information.
4569 symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
4570 }
4571 symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
4572 }
4573}
4574
4575
4576int ScriptDataImpl::ReadNumber(byte** source) {
4577 // Reads a number from symbol_data_ in base 128. The most significant
4578 // bit marks that there are more digits.
4579 // If the first byte is 0x80 (kNumberTerminator), it would normally
4580 // represent a leading zero. Since that is useless, and therefore won't
4581 // appear as the first digit of any actual value, it is used to
4582 // mark the end of the input stream.
4583 byte* data = *source;
4584 if (data >= symbol_data_end_) return -1;
4585 byte input = *data;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004586 if (input == PreparseDataConstants::kNumberTerminator) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004587 // End of stream marker.
4588 return -1;
4589 }
4590 int result = input & 0x7f;
4591 data++;
4592 while ((input & 0x80u) != 0) {
4593 if (data >= symbol_data_end_) return -1;
4594 input = *data;
4595 result = (result << 7) | (input & 0x7f);
4596 data++;
4597 }
4598 *source = data;
4599 return result;
4600}
4601
4602
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004603// Create a Scanner for the preparser to use as input, and preparse the source.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004604static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004605 bool allow_lazy,
Steve Block9fac8402011-05-12 15:51:54 +01004606 ParserRecorder* recorder) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004607 V8JavaScriptScanner scanner;
Steve Block9fac8402011-05-12 15:51:54 +01004608 scanner.Initialize(source);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004609 intptr_t stack_limit = StackGuard::real_climit();
4610 if (!preparser::PreParser::PreParseProgram(&scanner,
4611 recorder,
4612 allow_lazy,
4613 stack_limit)) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004614 Top::StackOverflow();
4615 return NULL;
4616 }
4617
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004618 // Extract the accumulated data from the recorder as a single
4619 // contiguous vector that we are responsible for disposing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004620 Vector<unsigned> store = recorder->ExtractData();
Steve Blocka7e24c12009-10-30 11:49:00 +00004621 return new ScriptDataImpl(store);
4622}
4623
4624
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004625// Preparse, but only collect data that is immediately useful,
4626// even if the preparser data is only used once.
Ben Murdochb0fe1622011-05-05 13:52:32 +01004627ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004628 v8::Extension* extension) {
4629 bool allow_lazy = FLAG_lazy && (extension == NULL);
4630 if (!allow_lazy) {
4631 // Partial preparsing is only about lazily compiled functions.
4632 // If we don't allow lazy compilation, the log data will be empty.
4633 return NULL;
4634 }
4635 PartialParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01004636 return DoPreParse(source, allow_lazy, &recorder);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004637}
4638
4639
Ben Murdochb0fe1622011-05-05 13:52:32 +01004640ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004641 v8::Extension* extension) {
4642 Handle<Script> no_script;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004643 bool allow_lazy = FLAG_lazy && (extension == NULL);
4644 CompleteParserRecorder recorder;
Steve Block9fac8402011-05-12 15:51:54 +01004645 return DoPreParse(source, allow_lazy, &recorder);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004646}
4647
4648
4649bool RegExpParser::ParseRegExp(FlatStringReader* input,
4650 bool multiline,
4651 RegExpCompileData* result) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004652 ASSERT(result != NULL);
4653 RegExpParser parser(input, &result->error, multiline);
4654 RegExpTree* tree = parser.ParsePattern();
4655 if (parser.failed()) {
4656 ASSERT(tree == NULL);
4657 ASSERT(!result->error.is_null());
4658 } else {
4659 ASSERT(tree != NULL);
4660 ASSERT(result->error.is_null());
4661 result->tree = tree;
4662 int capture_count = parser.captures_started();
4663 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
4664 result->contains_anchor = parser.contains_anchor();
4665 result->capture_count = capture_count;
4666 }
4667 return !parser.failed();
4668}
4669
4670
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004671bool ParserApi::Parse(CompilationInfo* info) {
Ben Murdochf87a2032010-10-22 12:50:53 +01004672 ASSERT(info->function() == NULL);
4673 FunctionLiteral* result = NULL;
4674 Handle<Script> script = info->script();
4675 if (info->is_lazy()) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004676 Parser parser(script, true, NULL, NULL);
Ben Murdochf87a2032010-10-22 12:50:53 +01004677 result = parser.ParseLazy(info->shared_info());
Leon Clarke4515c472010-02-03 11:58:03 +00004678 } else {
Ben Murdochf87a2032010-10-22 12:50:53 +01004679 bool allow_natives_syntax =
4680 FLAG_allow_natives_syntax || Bootstrapper::IsActive();
4681 ScriptDataImpl* pre_data = info->pre_parse_data();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004682 Parser parser(script, allow_natives_syntax, info->extension(), pre_data);
Ben Murdochf87a2032010-10-22 12:50:53 +01004683 if (pre_data != NULL && pre_data->has_error()) {
4684 Scanner::Location loc = pre_data->MessageLocation();
4685 const char* message = pre_data->BuildMessage();
4686 Vector<const char*> args = pre_data->BuildArgs();
4687 parser.ReportMessageAt(loc, message, args);
4688 DeleteArray(message);
4689 for (int i = 0; i < args.length(); i++) {
4690 DeleteArray(args[i]);
4691 }
4692 DeleteArray(args.start());
4693 ASSERT(Top::has_pending_exception());
4694 } else {
4695 Handle<String> source = Handle<String>(String::cast(script->source()));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004696 result = parser.ParseProgram(source, info->is_global());
Ben Murdochf87a2032010-10-22 12:50:53 +01004697 }
Leon Clarke4515c472010-02-03 11:58:03 +00004698 }
Ben Murdochf87a2032010-10-22 12:50:53 +01004699
4700 info->SetFunction(result);
4701 return (result != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00004702}
4703
Steve Blocka7e24c12009-10-30 11:49:00 +00004704} } // namespace v8::internal