blob: 6329371faa5f01736b49d7f8686ad7f4ceaa373b [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/ast.h"
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#include <cmath> // For isfinite.
8#include "src/builtins.h"
9#include "src/code-stubs.h"
10#include "src/contexts.h"
11#include "src/conversions.h"
12#include "src/hashmap.h"
13#include "src/parser.h"
14#include "src/property.h"
15#include "src/property-details.h"
16#include "src/scopes.h"
17#include "src/string-stream.h"
18#include "src/type-info.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000019
20namespace v8 {
21namespace internal {
22
Steve Blocka7e24c12009-10-30 11:49:00 +000023// ----------------------------------------------------------------------------
24// All the Accept member functions for each syntax tree node type.
25
Steve Block6ded16b2010-05-10 14:33:55 +010026#define DECL_ACCEPT(type) \
27 void type::Accept(AstVisitor* v) { v->Visit##type(this); }
Steve Blocka7e24c12009-10-30 11:49:00 +000028AST_NODE_LIST(DECL_ACCEPT)
29#undef DECL_ACCEPT
30
31
32// ----------------------------------------------------------------------------
33// Implementation of other node functionality.
34
Ben Murdoch3ef787d2012-04-12 10:51:47 +010035
Ben Murdochb8a8cc12014-11-26 15:28:44 +000036bool Expression::IsSmiLiteral() const {
37 return IsLiteral() && AsLiteral()->value()->IsSmi();
Steve Block6ded16b2010-05-10 14:33:55 +010038}
39
40
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041bool Expression::IsStringLiteral() const {
42 return IsLiteral() && AsLiteral()->value()->IsString();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010043}
44
45
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046bool Expression::IsNullLiteral() const {
47 return IsLiteral() && AsLiteral()->value()->IsNull();
Steve Block6ded16b2010-05-10 14:33:55 +010048}
49
50
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051bool Expression::IsUndefinedLiteral(Isolate* isolate) const {
52 const VariableProxy* var_proxy = AsVariableProxy();
53 if (var_proxy == NULL) return false;
54 Variable* var = var_proxy->var();
55 // The global identifier "undefined" is immutable. Everything
56 // else could be reassigned.
57 return var != NULL && var->location() == Variable::UNALLOCATED &&
58 var_proxy->raw_name()->IsOneByteEqualTo("undefined");
59}
60
61
Emily Bernierd0a1eb72015-03-24 16:35:39 -040062VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
63 : Expression(zone, position),
64 bit_field_(IsThisField::encode(var->is_this()) |
65 IsAssignedField::encode(false) |
66 IsResolvedField::encode(false)),
67 variable_feedback_slot_(FeedbackVectorICSlot::Invalid()),
68 raw_name_(var->raw_name()),
69 interface_(var->interface()) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +010070 BindTo(var);
71}
72
73
Ben Murdochb8a8cc12014-11-26 15:28:44 +000074VariableProxy::VariableProxy(Zone* zone, const AstRawString* name, bool is_this,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040075 Interface* interface, int position)
76 : Expression(zone, position),
77 bit_field_(IsThisField::encode(is_this) | IsAssignedField::encode(false) |
78 IsResolvedField::encode(false)),
79 variable_feedback_slot_(FeedbackVectorICSlot::Invalid()),
80 raw_name_(name),
81 interface_(interface) {}
Steve Blocka7e24c12009-10-30 11:49:00 +000082
83
Steve Blocka7e24c12009-10-30 11:49:00 +000084void VariableProxy::BindTo(Variable* var) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000085 DCHECK(!FLAG_harmony_modules || interface_->IsUnified(var->interface()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040086 DCHECK((is_this() && var->is_this()) || raw_name() == var->raw_name());
Steve Blocka7e24c12009-10-30 11:49:00 +000087 // Ideally CONST-ness should match. However, this is very hard to achieve
88 // because we don't know the exact semantics of conflicting (const and
89 // non-const) multiple variable declarations, const vars introduced via
90 // eval() etc. Const-ness and variable declarations are a complete mess
91 // in JS. Sigh...
Emily Bernierd0a1eb72015-03-24 16:35:39 -040092 set_var(var);
93 set_is_resolved();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000094 var->set_is_used();
Steve Blocka7e24c12009-10-30 11:49:00 +000095}
96
97
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098Assignment::Assignment(Zone* zone, Token::Value op, Expression* target,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040099 Expression* value, int pos)
100 : Expression(zone, pos),
101 bit_field_(IsUninitializedField::encode(false) |
102 KeyTypeField::encode(ELEMENT) |
103 StoreModeField::encode(STANDARD_STORE) |
104 TokenField::encode(op)),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100105 target_(target),
106 value_(value),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400107 binary_operation_(NULL) {}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100108
109
Steve Blocka7e24c12009-10-30 11:49:00 +0000110Token::Value Assignment::binary_op() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400111 switch (op()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000112 case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
113 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
114 case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
115 case Token::ASSIGN_SHL: return Token::SHL;
116 case Token::ASSIGN_SAR: return Token::SAR;
117 case Token::ASSIGN_SHR: return Token::SHR;
118 case Token::ASSIGN_ADD: return Token::ADD;
119 case Token::ASSIGN_SUB: return Token::SUB;
120 case Token::ASSIGN_MUL: return Token::MUL;
121 case Token::ASSIGN_DIV: return Token::DIV;
122 case Token::ASSIGN_MOD: return Token::MOD;
123 default: UNREACHABLE();
124 }
125 return Token::ILLEGAL;
126}
127
128
129bool FunctionLiteral::AllowsLazyCompilation() {
130 return scope()->AllowsLazyCompilation();
131}
132
133
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000134bool FunctionLiteral::AllowsLazyCompilationWithoutContext() {
135 return scope()->AllowsLazyCompilationWithoutContext();
136}
137
138
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100139int FunctionLiteral::start_position() const {
140 return scope()->start_position();
141}
142
143
144int FunctionLiteral::end_position() const {
145 return scope()->end_position();
146}
147
148
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149StrictMode FunctionLiteral::strict_mode() const {
150 return scope()->strict_mode();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100151}
152
153
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400154bool FunctionLiteral::uses_super_property() const {
155 DCHECK_NOT_NULL(scope());
156 return scope()->uses_super_property() || scope()->inner_uses_super_property();
157}
158
159
160bool FunctionLiteral::uses_super_constructor_call() const {
161 DCHECK_NOT_NULL(scope());
162 return scope()->uses_super_constructor_call() ||
163 scope()->inner_uses_super_constructor_call();
164}
165
166
167// Helper to find an existing shared function info in the baseline code for the
168// given function literal. Used to canonicalize SharedFunctionInfo objects.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169void FunctionLiteral::InitializeSharedInfo(
170 Handle<Code> unoptimized_code) {
171 for (RelocIterator it(*unoptimized_code); !it.done(); it.next()) {
172 RelocInfo* rinfo = it.rinfo();
173 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue;
174 Object* obj = rinfo->target_object();
175 if (obj->IsSharedFunctionInfo()) {
176 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
177 if (shared->start_position() == start_position()) {
178 shared_info_ = Handle<SharedFunctionInfo>(shared);
179 break;
180 }
181 }
182 }
183}
184
185
186ObjectLiteralProperty::ObjectLiteralProperty(Zone* zone,
187 AstValueFactory* ast_value_factory,
188 Literal* key, Expression* value,
189 bool is_static) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800190 emit_store_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +0000191 key_ = key;
192 value_ = value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000193 is_static_ = is_static;
194 if (key->raw_value()->EqualsString(ast_value_factory->proto_string())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000195 kind_ = PROTOTYPE;
196 } else if (value_->AsMaterializedLiteral() != NULL) {
197 kind_ = MATERIALIZED_LITERAL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000198 } else if (value_->IsLiteral()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000199 kind_ = CONSTANT;
200 } else {
201 kind_ = COMPUTED;
202 }
203}
204
205
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206ObjectLiteralProperty::ObjectLiteralProperty(Zone* zone, bool is_getter,
207 FunctionLiteral* value,
208 bool is_static) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800209 emit_store_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +0000210 value_ = value;
211 kind_ = is_getter ? GETTER : SETTER;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212 is_static_ = is_static;
Steve Blocka7e24c12009-10-30 11:49:00 +0000213}
214
215
Steve Blockd0582a62009-12-15 09:54:21 +0000216bool ObjectLiteral::Property::IsCompileTimeValue() {
217 return kind_ == CONSTANT ||
218 (kind_ == MATERIALIZED_LITERAL &&
219 CompileTimeValue::IsCompileTimeValue(value_));
220}
221
222
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800223void ObjectLiteral::Property::set_emit_store(bool emit_store) {
224 emit_store_ = emit_store;
225}
226
227
228bool ObjectLiteral::Property::emit_store() {
229 return emit_store_;
230}
231
232
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233void ObjectLiteral::CalculateEmitStore(Zone* zone) {
234 ZoneAllocationPolicy allocator(zone);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800235
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity,
237 allocator);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100238 for (int i = properties()->length() - 1; i >= 0; i--) {
239 ObjectLiteral::Property* property = properties()->at(i);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800240 Literal* literal = property->key();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241 if (literal->value()->IsNull()) continue;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100242 uint32_t hash = literal->Hash();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800243 // If the key of a computed property is in the table, do not emit
244 // a store for the property later.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245 if ((property->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL ||
246 property->kind() == ObjectLiteral::Property::COMPUTED) &&
247 table.Lookup(literal, hash, false, allocator) != NULL) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100248 property->set_emit_store(false);
249 } else {
250 // Add key to the table.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000251 table.Lookup(literal, hash, true, allocator);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800252 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800253 }
254}
255
256
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) {
258 return property != NULL &&
259 property->kind() != ObjectLiteral::Property::PROTOTYPE;
260}
261
262
263void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
264 if (!constant_properties_.is_null()) return;
265
266 // Allocate a fixed array to hold all the constant properties.
267 Handle<FixedArray> constant_properties = isolate->factory()->NewFixedArray(
268 boilerplate_properties_ * 2, TENURED);
269
270 int position = 0;
271 // Accumulate the value in local variables and store it at the end.
272 bool is_simple = true;
273 int depth_acc = 1;
274 uint32_t max_element_index = 0;
275 uint32_t elements = 0;
276 for (int i = 0; i < properties()->length(); i++) {
277 ObjectLiteral::Property* property = properties()->at(i);
278 if (!IsBoilerplateProperty(property)) {
279 is_simple = false;
280 continue;
281 }
282 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
283 if (m_literal != NULL) {
284 m_literal->BuildConstants(isolate);
285 if (m_literal->depth() >= depth_acc) depth_acc = m_literal->depth() + 1;
286 }
287
288 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
289 // value for COMPUTED properties, the real value is filled in at
290 // runtime. The enumeration order is maintained.
291 Handle<Object> key = property->key()->value();
292 Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
293
294 // Ensure objects that may, at any point in time, contain fields with double
295 // representation are always treated as nested objects. This is true for
296 // computed fields (value is undefined), and smi and double literals
297 // (value->IsNumber()).
298 // TODO(verwaest): Remove once we can store them inline.
299 if (FLAG_track_double_fields &&
300 (value->IsNumber() || value->IsUninitialized())) {
301 may_store_doubles_ = true;
302 }
303
304 is_simple = is_simple && !value->IsUninitialized();
305
306 // Keep track of the number of elements in the object literal and
307 // the largest element index. If the largest element index is
308 // much larger than the number of elements, creating an object
309 // literal with fast elements will be a waste of space.
310 uint32_t element_index = 0;
311 if (key->IsString()
312 && Handle<String>::cast(key)->AsArrayIndex(&element_index)
313 && element_index > max_element_index) {
314 max_element_index = element_index;
315 elements++;
316 } else if (key->IsSmi()) {
317 int key_value = Smi::cast(*key)->value();
318 if (key_value > 0
319 && static_cast<uint32_t>(key_value) > max_element_index) {
320 max_element_index = key_value;
321 }
322 elements++;
323 }
324
325 // Add name, value pair to the fixed array.
326 constant_properties->set(position++, *key);
327 constant_properties->set(position++, *value);
328 }
329
330 constant_properties_ = constant_properties;
331 fast_elements_ =
332 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
333 set_is_simple(is_simple);
334 set_depth(depth_acc);
335}
336
337
338void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
339 if (!constant_elements_.is_null()) return;
340
341 // Allocate a fixed array to hold all the object literals.
342 Handle<JSArray> array =
343 isolate->factory()->NewJSArray(0, FAST_HOLEY_SMI_ELEMENTS);
344 JSArray::Expand(array, values()->length());
345
346 // Fill in the literals.
347 bool is_simple = true;
348 int depth_acc = 1;
349 bool is_holey = false;
350 for (int i = 0, n = values()->length(); i < n; i++) {
351 Expression* element = values()->at(i);
352 MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
353 if (m_literal != NULL) {
354 m_literal->BuildConstants(isolate);
355 if (m_literal->depth() + 1 > depth_acc) {
356 depth_acc = m_literal->depth() + 1;
357 }
358 }
359 Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
360 if (boilerplate_value->IsTheHole()) {
361 is_holey = true;
362 } else if (boilerplate_value->IsUninitialized()) {
363 is_simple = false;
364 JSObject::SetOwnElement(
365 array, i, handle(Smi::FromInt(0), isolate), SLOPPY).Assert();
366 } else {
367 JSObject::SetOwnElement(array, i, boilerplate_value, SLOPPY).Assert();
368 }
369 }
370
371 Handle<FixedArrayBase> element_values(array->elements());
372
373 // Simple and shallow arrays can be lazily copied, we transform the
374 // elements array to a copy-on-write array.
375 if (is_simple && depth_acc == 1 && values()->length() > 0 &&
376 array->HasFastSmiOrObjectElements()) {
377 element_values->set_map(isolate->heap()->fixed_cow_array_map());
378 }
379
380 // Remember both the literal's constant values as well as the ElementsKind
381 // in a 2-element FixedArray.
382 Handle<FixedArray> literals = isolate->factory()->NewFixedArray(2, TENURED);
383
384 ElementsKind kind = array->GetElementsKind();
385 kind = is_holey ? GetHoleyElementsKind(kind) : GetPackedElementsKind(kind);
386
387 literals->set(0, Smi::FromInt(kind));
388 literals->set(1, *element_values);
389
390 constant_elements_ = literals;
391 set_is_simple(is_simple);
392 set_depth(depth_acc);
393}
394
395
396Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
397 Isolate* isolate) {
398 if (expression->IsLiteral()) {
399 return expression->AsLiteral()->value();
400 }
401 if (CompileTimeValue::IsCompileTimeValue(expression)) {
402 return CompileTimeValue::GetValue(isolate, expression);
403 }
404 return isolate->factory()->uninitialized_value();
405}
406
407
408void MaterializedLiteral::BuildConstants(Isolate* isolate) {
409 if (IsArrayLiteral()) {
410 return AsArrayLiteral()->BuildConstantElements(isolate);
411 }
412 if (IsObjectLiteral()) {
413 return AsObjectLiteral()->BuildConstantProperties(isolate);
414 }
415 DCHECK(IsRegExpLiteral());
416 DCHECK(depth() >= 1); // Depth should be initialized.
417}
418
419
420void TargetCollector::AddTarget(Label* target, Zone* zone) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000421 // Add the label to the collector, but discard duplicates.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000422 int length = targets_.length();
Steve Blocka7e24c12009-10-30 11:49:00 +0000423 for (int i = 0; i < length; i++) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000424 if (targets_[i] == target) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000425 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000426 targets_.Add(target, zone);
Steve Blocka7e24c12009-10-30 11:49:00 +0000427}
428
429
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000430void UnaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
431 // TODO(olivf) If this Operation is used in a test context, then the
432 // expression has a ToBoolean stub and we want to collect the type
433 // information. However the GraphBuilder expects it to be on the instruction
434 // corresponding to the TestContext, therefore we have to store it here and
435 // not on the operand.
436 set_to_boolean_types(oracle->ToBooleanTypes(expression()->test_id()));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100437}
438
439
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440void BinaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
441 // TODO(olivf) If this Operation is used in a test context, then the right
442 // hand side has a ToBoolean stub and we want to collect the type information.
443 // However the GraphBuilder expects it to be on the instruction corresponding
444 // to the TestContext, therefore we have to store it here and not on the
445 // right hand operand.
446 set_to_boolean_types(oracle->ToBooleanTypes(right()->test_id()));
447}
448
449
450bool BinaryOperation::ResultOverwriteAllowed() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400451 switch (op()) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100452 case Token::COMMA:
453 case Token::OR:
454 case Token::AND:
455 return false;
456 case Token::BIT_OR:
457 case Token::BIT_XOR:
458 case Token::BIT_AND:
459 case Token::SHL:
460 case Token::SAR:
461 case Token::SHR:
462 case Token::ADD:
463 case Token::SUB:
464 case Token::MUL:
465 case Token::DIV:
466 case Token::MOD:
467 return true;
468 default:
469 UNREACHABLE();
470 }
471 return false;
472}
473
474
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100475static bool IsTypeof(Expression* expr) {
476 UnaryOperation* maybe_unary = expr->AsUnaryOperation();
477 return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF;
478}
479
480
481// Check for the pattern: typeof <expression> equals <string literal>.
482static bool MatchLiteralCompareTypeof(Expression* left,
483 Token::Value op,
484 Expression* right,
485 Expression** expr,
486 Handle<String>* check) {
487 if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
488 *expr = left->AsUnaryOperation()->expression();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000489 *check = Handle<String>::cast(right->AsLiteral()->value());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100490 return true;
491 }
492 return false;
493}
494
495
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000496bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
497 Handle<String>* check) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100498 return MatchLiteralCompareTypeof(left_, op_, right_, expr, check) ||
499 MatchLiteralCompareTypeof(right_, op_, left_, expr, check);
500}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000501
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000502
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100503static bool IsVoidOfLiteral(Expression* expr) {
504 UnaryOperation* maybe_unary = expr->AsUnaryOperation();
505 return maybe_unary != NULL &&
506 maybe_unary->op() == Token::VOID &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000507 maybe_unary->expression()->IsLiteral();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100508}
509
510
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511// Check for the pattern: void <literal> equals <expression> or
512// undefined equals <expression>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100513static bool MatchLiteralCompareUndefined(Expression* left,
514 Token::Value op,
515 Expression* right,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000516 Expression** expr,
517 Isolate* isolate) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100518 if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
519 *expr = right;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000520 return true;
521 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000522 if (left->IsUndefinedLiteral(isolate) && Token::IsEqualityOp(op)) {
523 *expr = right;
524 return true;
525 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000526 return false;
527}
528
529
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000530bool CompareOperation::IsLiteralCompareUndefined(
531 Expression** expr, Isolate* isolate) {
532 return MatchLiteralCompareUndefined(left_, op_, right_, expr, isolate) ||
533 MatchLiteralCompareUndefined(right_, op_, left_, expr, isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100534}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000535
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000536
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100537// Check for the pattern: null equals <expression>
538static bool MatchLiteralCompareNull(Expression* left,
539 Token::Value op,
540 Expression* right,
541 Expression** expr) {
542 if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
543 *expr = right;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000544 return true;
545 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000546 return false;
547}
548
549
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100550bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
551 return MatchLiteralCompareNull(left_, op_, right_, expr) ||
552 MatchLiteralCompareNull(right_, op_, left_, expr);
553}
554
555
Steve Blocka7e24c12009-10-30 11:49:00 +0000556// ----------------------------------------------------------------------------
Ben Murdochb0fe1622011-05-05 13:52:32 +0100557// Inlining support
558
Ben Murdoch8b112d22011-06-08 16:22:53 +0100559bool Declaration::IsInlineable() const {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100560 return proxy()->var()->IsStackAllocated();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100561}
562
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100563bool FunctionDeclaration::IsInlineable() const {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100564 return false;
565}
566
567
Ben Murdochb0fe1622011-05-05 13:52:32 +0100568// ----------------------------------------------------------------------------
569// Recording of type feedback
570
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000571// TODO(rossberg): all RecordTypeFeedback functions should disappear
572// once we use the common type field in the AST consistently.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100573
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000574void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400575 set_to_boolean_types(oracle->ToBooleanTypes(test_id()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576}
577
578
579bool Call::IsUsingCallFeedbackSlot(Isolate* isolate) const {
580 CallType call_type = GetCallType(isolate);
581 return (call_type != POSSIBLY_EVAL_CALL);
582}
583
584
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400585FeedbackVectorRequirements Call::ComputeFeedbackRequirements(Isolate* isolate) {
586 int ic_slots = IsUsingCallFeedbackSlot(isolate) ? 1 : 0;
587 return FeedbackVectorRequirements(0, ic_slots);
588}
589
590
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000591Call::CallType Call::GetCallType(Isolate* isolate) const {
592 VariableProxy* proxy = expression()->AsVariableProxy();
593 if (proxy != NULL) {
594 if (proxy->var()->is_possibly_eval(isolate)) {
595 return POSSIBLY_EVAL_CALL;
596 } else if (proxy->var()->IsUnallocated()) {
597 return GLOBAL_CALL;
598 } else if (proxy->var()->IsLookupSlot()) {
599 return LOOKUP_SLOT_CALL;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100600 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100601 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100602
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400603 if (expression()->AsSuperReference() != NULL) return SUPER_CALL;
604
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605 Property* property = expression()->AsProperty();
606 return property != NULL ? PROPERTY_CALL : OTHER_CALL;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100607}
608
609
610bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000611 LookupIterator* it) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100612 target_ = Handle<JSFunction>::null();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000613 cell_ = Handle<Cell>::null();
614 DCHECK(it->IsFound() && it->GetHolder<JSObject>().is_identical_to(global));
615 cell_ = it->GetPropertyCell();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100616 if (cell_->value()->IsJSFunction()) {
617 Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
618 // If the function is in new space we assume it's more likely to
619 // change and thus prefer the general IC code.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000620 if (!it->isolate()->heap()->InNewSpace(*candidate)) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100621 target_ = candidate;
622 return true;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100623 }
624 }
625 return false;
626}
627
628
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100629void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400630 FeedbackVectorSlot allocation_site_feedback_slot =
631 FLAG_pretenuring_call_new ? AllocationSiteFeedbackSlot()
632 : CallNewFeedbackSlot();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000633 allocation_site_ =
634 oracle->GetCallNewAllocationSite(allocation_site_feedback_slot);
635 is_monomorphic_ = oracle->CallNewIsMonomorphic(CallNewFeedbackSlot());
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100636 if (is_monomorphic_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000637 target_ = oracle->GetCallNewTarget(CallNewFeedbackSlot());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100638 }
639}
640
641
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100642void ObjectLiteral::Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000643 TypeFeedbackId id = key()->LiteralFeedbackId();
644 SmallMapList maps;
645 oracle->CollectReceiverTypes(id, &maps);
646 receiver_type_ = maps.length() == 1 ? maps.at(0)
647 : Handle<Map>::null();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100648}
649
650
Ben Murdochb0fe1622011-05-05 13:52:32 +0100651// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000652// Implementation of AstVisitor
653
Steve Block3ce2e202009-11-05 08:53:23 +0000654void AstVisitor::VisitDeclarations(ZoneList<Declaration*>* declarations) {
655 for (int i = 0; i < declarations->length(); i++) {
656 Visit(declarations->at(i));
657 }
658}
659
660
Steve Blocka7e24c12009-10-30 11:49:00 +0000661void AstVisitor::VisitStatements(ZoneList<Statement*>* statements) {
662 for (int i = 0; i < statements->length(); i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000663 Statement* stmt = statements->at(i);
664 Visit(stmt);
665 if (stmt->IsJump()) break;
Steve Blocka7e24c12009-10-30 11:49:00 +0000666 }
667}
668
669
670void AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) {
671 for (int i = 0; i < expressions->length(); i++) {
672 // The variable statement visiting code may pass NULL expressions
673 // to this code. Maybe this should be handled by introducing an
674 // undefined expression or literal? Revisit this code if this
675 // changes
676 Expression* expression = expressions->at(i);
677 if (expression != NULL) Visit(expression);
678 }
679}
680
681
682// ----------------------------------------------------------------------------
683// Regular expressions
684
685#define MAKE_ACCEPT(Name) \
686 void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) { \
687 return visitor->Visit##Name(this, data); \
688 }
689FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT)
690#undef MAKE_ACCEPT
691
692#define MAKE_TYPE_CASE(Name) \
693 RegExp##Name* RegExpTree::As##Name() { \
694 return NULL; \
695 } \
696 bool RegExpTree::Is##Name() { return false; }
697FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
698#undef MAKE_TYPE_CASE
699
700#define MAKE_TYPE_CASE(Name) \
701 RegExp##Name* RegExp##Name::As##Name() { \
702 return this; \
703 } \
704 bool RegExp##Name::Is##Name() { return true; }
705FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
706#undef MAKE_TYPE_CASE
707
Steve Blocka7e24c12009-10-30 11:49:00 +0000708
709static Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) {
710 Interval result = Interval::Empty();
711 for (int i = 0; i < children->length(); i++)
712 result = result.Union(children->at(i)->CaptureRegisters());
713 return result;
714}
715
716
717Interval RegExpAlternative::CaptureRegisters() {
718 return ListCaptureRegisters(nodes());
719}
720
721
722Interval RegExpDisjunction::CaptureRegisters() {
723 return ListCaptureRegisters(alternatives());
724}
725
726
727Interval RegExpLookahead::CaptureRegisters() {
728 return body()->CaptureRegisters();
729}
730
731
732Interval RegExpCapture::CaptureRegisters() {
733 Interval self(StartRegister(index()), EndRegister(index()));
734 return self.Union(body()->CaptureRegisters());
735}
736
737
738Interval RegExpQuantifier::CaptureRegisters() {
739 return body()->CaptureRegisters();
740}
741
742
Ben Murdochf87a2032010-10-22 12:50:53 +0100743bool RegExpAssertion::IsAnchoredAtStart() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000744 return assertion_type() == RegExpAssertion::START_OF_INPUT;
Steve Blocka7e24c12009-10-30 11:49:00 +0000745}
746
747
Ben Murdochf87a2032010-10-22 12:50:53 +0100748bool RegExpAssertion::IsAnchoredAtEnd() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000749 return assertion_type() == RegExpAssertion::END_OF_INPUT;
Ben Murdochf87a2032010-10-22 12:50:53 +0100750}
751
752
753bool RegExpAlternative::IsAnchoredAtStart() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000754 ZoneList<RegExpTree*>* nodes = this->nodes();
755 for (int i = 0; i < nodes->length(); i++) {
756 RegExpTree* node = nodes->at(i);
Ben Murdochf87a2032010-10-22 12:50:53 +0100757 if (node->IsAnchoredAtStart()) { return true; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000758 if (node->max_match() > 0) { return false; }
759 }
760 return false;
761}
762
763
Ben Murdochf87a2032010-10-22 12:50:53 +0100764bool RegExpAlternative::IsAnchoredAtEnd() {
765 ZoneList<RegExpTree*>* nodes = this->nodes();
766 for (int i = nodes->length() - 1; i >= 0; i--) {
767 RegExpTree* node = nodes->at(i);
768 if (node->IsAnchoredAtEnd()) { return true; }
769 if (node->max_match() > 0) { return false; }
770 }
771 return false;
772}
773
774
775bool RegExpDisjunction::IsAnchoredAtStart() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000776 ZoneList<RegExpTree*>* alternatives = this->alternatives();
777 for (int i = 0; i < alternatives->length(); i++) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100778 if (!alternatives->at(i)->IsAnchoredAtStart())
Steve Blocka7e24c12009-10-30 11:49:00 +0000779 return false;
780 }
781 return true;
782}
783
784
Ben Murdochf87a2032010-10-22 12:50:53 +0100785bool RegExpDisjunction::IsAnchoredAtEnd() {
786 ZoneList<RegExpTree*>* alternatives = this->alternatives();
787 for (int i = 0; i < alternatives->length(); i++) {
788 if (!alternatives->at(i)->IsAnchoredAtEnd())
789 return false;
790 }
791 return true;
Steve Blocka7e24c12009-10-30 11:49:00 +0000792}
793
794
Ben Murdochf87a2032010-10-22 12:50:53 +0100795bool RegExpLookahead::IsAnchoredAtStart() {
796 return is_positive() && body()->IsAnchoredAtStart();
797}
798
799
800bool RegExpCapture::IsAnchoredAtStart() {
801 return body()->IsAnchoredAtStart();
802}
803
804
805bool RegExpCapture::IsAnchoredAtEnd() {
806 return body()->IsAnchoredAtEnd();
Steve Blocka7e24c12009-10-30 11:49:00 +0000807}
808
809
810// Convert regular expression trees to a simple sexp representation.
811// This representation should be different from the input grammar
812// in as many cases as possible, to make it more difficult for incorrect
813// parses to look as correct ones which is likely if the input and
814// output formats are alike.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000815class RegExpUnparser FINAL : public RegExpVisitor {
Steve Blocka7e24c12009-10-30 11:49:00 +0000816 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400817 RegExpUnparser(std::ostream& os, Zone* zone) : os_(os), zone_(zone) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000818 void VisitCharacterRange(CharacterRange that);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000819#define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, \
820 void* data) OVERRIDE;
Steve Blocka7e24c12009-10-30 11:49:00 +0000821 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
822#undef MAKE_CASE
823 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400824 std::ostream& os_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000825 Zone* zone_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000826};
827
828
Steve Blocka7e24c12009-10-30 11:49:00 +0000829void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000830 os_ << "(|";
Steve Blocka7e24c12009-10-30 11:49:00 +0000831 for (int i = 0; i < that->alternatives()->length(); i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000832 os_ << " ";
Steve Blocka7e24c12009-10-30 11:49:00 +0000833 that->alternatives()->at(i)->Accept(this, data);
834 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835 os_ << ")";
Steve Blocka7e24c12009-10-30 11:49:00 +0000836 return NULL;
837}
838
839
840void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000841 os_ << "(:";
Steve Blocka7e24c12009-10-30 11:49:00 +0000842 for (int i = 0; i < that->nodes()->length(); i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000843 os_ << " ";
Steve Blocka7e24c12009-10-30 11:49:00 +0000844 that->nodes()->at(i)->Accept(this, data);
845 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000846 os_ << ")";
Steve Blocka7e24c12009-10-30 11:49:00 +0000847 return NULL;
848}
849
850
851void RegExpUnparser::VisitCharacterRange(CharacterRange that) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000852 os_ << AsUC16(that.from());
Steve Blocka7e24c12009-10-30 11:49:00 +0000853 if (!that.IsSingleton()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000854 os_ << "-" << AsUC16(that.to());
Steve Blocka7e24c12009-10-30 11:49:00 +0000855 }
856}
857
858
859
860void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that,
861 void* data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000862 if (that->is_negated()) os_ << "^";
863 os_ << "[";
864 for (int i = 0; i < that->ranges(zone_)->length(); i++) {
865 if (i > 0) os_ << " ";
866 VisitCharacterRange(that->ranges(zone_)->at(i));
Steve Blocka7e24c12009-10-30 11:49:00 +0000867 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000868 os_ << "]";
Steve Blocka7e24c12009-10-30 11:49:00 +0000869 return NULL;
870}
871
872
873void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000874 switch (that->assertion_type()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000875 case RegExpAssertion::START_OF_INPUT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000876 os_ << "@^i";
Steve Blocka7e24c12009-10-30 11:49:00 +0000877 break;
878 case RegExpAssertion::END_OF_INPUT:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000879 os_ << "@$i";
Steve Blocka7e24c12009-10-30 11:49:00 +0000880 break;
881 case RegExpAssertion::START_OF_LINE:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000882 os_ << "@^l";
Steve Blocka7e24c12009-10-30 11:49:00 +0000883 break;
884 case RegExpAssertion::END_OF_LINE:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000885 os_ << "@$l";
Steve Blocka7e24c12009-10-30 11:49:00 +0000886 break;
887 case RegExpAssertion::BOUNDARY:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000888 os_ << "@b";
Steve Blocka7e24c12009-10-30 11:49:00 +0000889 break;
890 case RegExpAssertion::NON_BOUNDARY:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891 os_ << "@B";
Steve Blocka7e24c12009-10-30 11:49:00 +0000892 break;
893 }
894 return NULL;
895}
896
897
898void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899 os_ << "'";
Steve Blocka7e24c12009-10-30 11:49:00 +0000900 Vector<const uc16> chardata = that->data();
901 for (int i = 0; i < chardata.length(); i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000902 os_ << AsUC16(chardata[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +0000903 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000904 os_ << "'";
Steve Blocka7e24c12009-10-30 11:49:00 +0000905 return NULL;
906}
907
908
909void* RegExpUnparser::VisitText(RegExpText* that, void* data) {
910 if (that->elements()->length() == 1) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000911 that->elements()->at(0).tree()->Accept(this, data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000912 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000913 os_ << "(!";
Steve Blocka7e24c12009-10-30 11:49:00 +0000914 for (int i = 0; i < that->elements()->length(); i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000915 os_ << " ";
916 that->elements()->at(i).tree()->Accept(this, data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000917 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000918 os_ << ")";
Steve Blocka7e24c12009-10-30 11:49:00 +0000919 }
920 return NULL;
921}
922
923
924void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000925 os_ << "(# " << that->min() << " ";
Steve Blocka7e24c12009-10-30 11:49:00 +0000926 if (that->max() == RegExpTree::kInfinity) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000927 os_ << "- ";
Steve Blocka7e24c12009-10-30 11:49:00 +0000928 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000929 os_ << that->max() << " ";
Steve Blocka7e24c12009-10-30 11:49:00 +0000930 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000931 os_ << (that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n ");
Steve Blocka7e24c12009-10-30 11:49:00 +0000932 that->body()->Accept(this, data);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000933 os_ << ")";
Steve Blocka7e24c12009-10-30 11:49:00 +0000934 return NULL;
935}
936
937
938void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000939 os_ << "(^ ";
Steve Blocka7e24c12009-10-30 11:49:00 +0000940 that->body()->Accept(this, data);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000941 os_ << ")";
Steve Blocka7e24c12009-10-30 11:49:00 +0000942 return NULL;
943}
944
945
946void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000947 os_ << "(-> " << (that->is_positive() ? "+ " : "- ");
Steve Blocka7e24c12009-10-30 11:49:00 +0000948 that->body()->Accept(this, data);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000949 os_ << ")";
Steve Blocka7e24c12009-10-30 11:49:00 +0000950 return NULL;
951}
952
953
954void* RegExpUnparser::VisitBackReference(RegExpBackReference* that,
955 void* data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000956 os_ << "(<- " << that->index() << ")";
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 return NULL;
958}
959
960
961void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000962 os_ << '%';
Steve Blocka7e24c12009-10-30 11:49:00 +0000963 return NULL;
964}
965
966
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400967std::ostream& RegExpTree::Print(std::ostream& os, Zone* zone) { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000968 RegExpUnparser unparser(os, zone);
Steve Blocka7e24c12009-10-30 11:49:00 +0000969 Accept(&unparser, NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000970 return os;
Steve Blocka7e24c12009-10-30 11:49:00 +0000971}
972
973
974RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
975 : alternatives_(alternatives) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000976 DCHECK(alternatives->length() > 1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000977 RegExpTree* first_alternative = alternatives->at(0);
978 min_match_ = first_alternative->min_match();
979 max_match_ = first_alternative->max_match();
980 for (int i = 1; i < alternatives->length(); i++) {
981 RegExpTree* alternative = alternatives->at(i);
982 min_match_ = Min(min_match_, alternative->min_match());
983 max_match_ = Max(max_match_, alternative->max_match());
984 }
985}
986
987
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000988static int IncreaseBy(int previous, int increase) {
989 if (RegExpTree::kInfinity - previous < increase) {
990 return RegExpTree::kInfinity;
991 } else {
992 return previous + increase;
993 }
994}
995
Steve Blocka7e24c12009-10-30 11:49:00 +0000996RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
997 : nodes_(nodes) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998 DCHECK(nodes->length() > 1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000999 min_match_ = 0;
1000 max_match_ = 0;
1001 for (int i = 0; i < nodes->length(); i++) {
1002 RegExpTree* node = nodes->at(i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001003 int node_min_match = node->min_match();
1004 min_match_ = IncreaseBy(min_match_, node_min_match);
Steve Blocka7e24c12009-10-30 11:49:00 +00001005 int node_max_match = node->max_match();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001006 max_match_ = IncreaseBy(max_match_, node_max_match);
Steve Blocka7e24c12009-10-30 11:49:00 +00001007 }
1008}
1009
Steve Block6ded16b2010-05-10 14:33:55 +01001010
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001011CaseClause::CaseClause(Zone* zone, Expression* label,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001012 ZoneList<Statement*>* statements, int pos)
1013 : Expression(zone, pos),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001014 label_(label),
Ben Murdochb0fe1622011-05-05 13:52:32 +01001015 statements_(statements),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001016 compare_type_(Type::None(zone)) {}
Kristian Monsen25f61362010-05-21 11:50:48 +01001017
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001018
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001019uint32_t Literal::Hash() {
1020 return raw_value()->IsString()
1021 ? raw_value()->AsString()->hash()
1022 : ComputeLongHash(double_to_uint64(raw_value()->AsNumber()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001023}
1024
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001025
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001026// static
1027bool Literal::Match(void* literal1, void* literal2) {
1028 const AstValue* x = static_cast<Literal*>(literal1)->raw_value();
1029 const AstValue* y = static_cast<Literal*>(literal2)->raw_value();
1030 return (x->IsString() && y->IsString() && *x->AsString() == *y->AsString()) ||
1031 (x->IsNumber() && y->IsNumber() && x->AsNumber() == y->AsNumber());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001032}
1033
1034
Steve Blocka7e24c12009-10-30 11:49:00 +00001035} } // namespace v8::internal