v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ast.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // 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 "ast.h"
29 
30 #include <cmath> // For isfinite.
31 #include "builtins.h"
32 #include "code-stubs.h"
33 #include "contexts.h"
34 #include "conversions.h"
35 #include "hashmap.h"
36 #include "parser.h"
37 #include "property-details.h"
38 #include "property.h"
39 #include "scopes.h"
40 #include "string-stream.h"
41 #include "type-info.h"
42 
43 namespace v8 {
44 namespace internal {
45 
46 // ----------------------------------------------------------------------------
47 // All the Accept member functions for each syntax tree node type.
48 
49 #define DECL_ACCEPT(type) \
50  void type::Accept(AstVisitor* v) { v->Visit##type(this); }
52 #undef DECL_ACCEPT
53 
54 
55 // ----------------------------------------------------------------------------
56 // Implementation of other node functionality.
57 
58 
60  return AsLiteral() != NULL && AsLiteral()->value()->IsSmi();
61 }
62 
63 
65  return AsLiteral() != NULL && AsLiteral()->value()->IsString();
66 }
67 
68 
70  return AsLiteral() != NULL && AsLiteral()->value()->IsNull();
71 }
72 
73 
75  VariableProxy* var_proxy = AsVariableProxy();
76  if (var_proxy == NULL) return false;
77  Variable* var = var_proxy->var();
78  // The global identifier "undefined" is immutable. Everything
79  // else could be reassigned.
80  return var != NULL && var->location() == Variable::UNALLOCATED &&
81  var_proxy->name()->Equals(isolate->heap()->undefined_string());
82 }
83 
84 
85 VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
86  : Expression(zone, position),
87  name_(var->name()),
88  var_(NULL), // Will be set by the call to BindTo.
89  is_this_(var->is_this()),
90  is_trivial_(false),
91  is_lvalue_(false),
92  interface_(var->interface()) {
93  BindTo(var);
94 }
95 
96 
97 VariableProxy::VariableProxy(Zone* zone,
99  bool is_this,
100  Interface* interface,
101  int position)
102  : Expression(zone, position),
103  name_(name),
104  var_(NULL),
105  is_this_(is_this),
106  is_trivial_(false),
107  is_lvalue_(false),
108  interface_(interface) {
109  // Names must be canonicalized for fast equality checks.
110  ASSERT(name->IsInternalizedString());
111 }
112 
113 
114 void VariableProxy::BindTo(Variable* var) {
115  ASSERT(var_ == NULL); // must be bound only once
116  ASSERT(var != NULL); // must bind
117  ASSERT(!FLAG_harmony_modules || interface_->IsUnified(var->interface()));
118  ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name()));
119  // Ideally CONST-ness should match. However, this is very hard to achieve
120  // because we don't know the exact semantics of conflicting (const and
121  // non-const) multiple variable declarations, const vars introduced via
122  // eval() etc. Const-ness and variable declarations are a complete mess
123  // in JS. Sigh...
124  var_ = var;
125  var->set_is_used(true);
126 }
127 
128 
129 Assignment::Assignment(Zone* zone,
130  Token::Value op,
131  Expression* target,
132  Expression* value,
133  int pos)
134  : Expression(zone, pos),
135  op_(op),
136  target_(target),
137  value_(value),
138  binary_operation_(NULL),
139  assignment_id_(GetNextId(zone)),
140  is_uninitialized_(false),
141  store_mode_(STANDARD_STORE) { }
142 
143 
144 Token::Value Assignment::binary_op() const {
145  switch (op_) {
146  case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
147  case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
148  case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
149  case Token::ASSIGN_SHL: return Token::SHL;
150  case Token::ASSIGN_SAR: return Token::SAR;
151  case Token::ASSIGN_SHR: return Token::SHR;
152  case Token::ASSIGN_ADD: return Token::ADD;
153  case Token::ASSIGN_SUB: return Token::SUB;
154  case Token::ASSIGN_MUL: return Token::MUL;
155  case Token::ASSIGN_DIV: return Token::DIV;
156  case Token::ASSIGN_MOD: return Token::MOD;
157  default: UNREACHABLE();
158  }
159  return Token::ILLEGAL;
160 }
161 
162 
163 bool FunctionLiteral::AllowsLazyCompilation() {
164  return scope()->AllowsLazyCompilation();
165 }
166 
167 
168 bool FunctionLiteral::AllowsLazyCompilationWithoutContext() {
169  return scope()->AllowsLazyCompilationWithoutContext();
170 }
171 
172 
173 int FunctionLiteral::start_position() const {
174  return scope()->start_position();
175 }
176 
177 
178 int FunctionLiteral::end_position() const {
179  return scope()->end_position();
180 }
181 
182 
183 StrictMode FunctionLiteral::strict_mode() const {
184  return scope()->strict_mode();
185 }
186 
187 
188 void FunctionLiteral::InitializeSharedInfo(
189  Handle<Code> unoptimized_code) {
190  for (RelocIterator it(*unoptimized_code); !it.done(); it.next()) {
191  RelocInfo* rinfo = it.rinfo();
192  if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue;
193  Object* obj = rinfo->target_object();
194  if (obj->IsSharedFunctionInfo()) {
195  SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
196  if (shared->start_position() == start_position()) {
197  shared_info_ = Handle<SharedFunctionInfo>(shared);
198  break;
199  }
200  }
201  }
202 }
203 
204 
205 ObjectLiteralProperty::ObjectLiteralProperty(
206  Zone* zone, Literal* key, Expression* value) {
207  emit_store_ = true;
208  key_ = key;
209  value_ = value;
210  Object* k = *key->value();
211  if (k->IsInternalizedString() &&
212  zone->isolate()->heap()->proto_string()->Equals(String::cast(k))) {
213  kind_ = PROTOTYPE;
214  } else if (value_->AsMaterializedLiteral() != NULL) {
215  kind_ = MATERIALIZED_LITERAL;
216  } else if (value_->AsLiteral() != NULL) {
217  kind_ = CONSTANT;
218  } else {
219  kind_ = COMPUTED;
220  }
221 }
222 
223 
224 ObjectLiteralProperty::ObjectLiteralProperty(
225  Zone* zone, bool is_getter, FunctionLiteral* value) {
226  emit_store_ = true;
227  value_ = value;
228  kind_ = is_getter ? GETTER : SETTER;
229 }
230 
231 
232 bool ObjectLiteral::Property::IsCompileTimeValue() {
233  return kind_ == CONSTANT ||
234  (kind_ == MATERIALIZED_LITERAL &&
236 }
237 
238 
239 void ObjectLiteral::Property::set_emit_store(bool emit_store) {
240  emit_store_ = emit_store;
241 }
242 
243 
244 bool ObjectLiteral::Property::emit_store() {
245  return emit_store_;
246 }
247 
248 
249 void ObjectLiteral::CalculateEmitStore(Zone* zone) {
250  ZoneAllocationPolicy allocator(zone);
251 
253  allocator);
254  for (int i = properties()->length() - 1; i >= 0; i--) {
255  ObjectLiteral::Property* property = properties()->at(i);
256  Literal* literal = property->key();
257  if (literal->value()->IsNull()) continue;
258  uint32_t hash = literal->Hash();
259  // If the key of a computed property is in the table, do not emit
260  // a store for the property later.
261  if ((property->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL ||
262  property->kind() == ObjectLiteral::Property::COMPUTED) &&
263  table.Lookup(literal, hash, false, allocator) != NULL) {
264  property->set_emit_store(false);
265  } else {
266  // Add key to the table.
267  table.Lookup(literal, hash, true, allocator);
268  }
269  }
270 }
271 
272 
273 bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) {
274  return property != NULL &&
275  property->kind() != ObjectLiteral::Property::PROTOTYPE;
276 }
277 
278 
279 void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
280  if (!constant_properties_.is_null()) return;
281 
282  // Allocate a fixed array to hold all the constant properties.
283  Handle<FixedArray> constant_properties = isolate->factory()->NewFixedArray(
284  boilerplate_properties_ * 2, TENURED);
285 
286  int position = 0;
287  // Accumulate the value in local variables and store it at the end.
288  bool is_simple = true;
289  int depth_acc = 1;
290  uint32_t max_element_index = 0;
291  uint32_t elements = 0;
292  for (int i = 0; i < properties()->length(); i++) {
293  ObjectLiteral::Property* property = properties()->at(i);
294  if (!IsBoilerplateProperty(property)) {
295  is_simple = false;
296  continue;
297  }
298  MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
299  if (m_literal != NULL) {
300  m_literal->BuildConstants(isolate);
301  if (m_literal->depth() >= depth_acc) depth_acc = m_literal->depth() + 1;
302  }
303 
304  // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
305  // value for COMPUTED properties, the real value is filled in at
306  // runtime. The enumeration order is maintained.
307  Handle<Object> key = property->key()->value();
308  Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
309 
310  // Ensure objects that may, at any point in time, contain fields with double
311  // representation are always treated as nested objects. This is true for
312  // computed fields (value is undefined), and smi and double literals
313  // (value->IsNumber()).
314  // TODO(verwaest): Remove once we can store them inline.
315  if (FLAG_track_double_fields &&
316  (value->IsNumber() || value->IsUninitialized())) {
317  may_store_doubles_ = true;
318  }
319 
320  is_simple = is_simple && !value->IsUninitialized();
321 
322  // Keep track of the number of elements in the object literal and
323  // the largest element index. If the largest element index is
324  // much larger than the number of elements, creating an object
325  // literal with fast elements will be a waste of space.
326  uint32_t element_index = 0;
327  if (key->IsString()
328  && Handle<String>::cast(key)->AsArrayIndex(&element_index)
329  && element_index > max_element_index) {
330  max_element_index = element_index;
331  elements++;
332  } else if (key->IsSmi()) {
333  int key_value = Smi::cast(*key)->value();
334  if (key_value > 0
335  && static_cast<uint32_t>(key_value) > max_element_index) {
336  max_element_index = key_value;
337  }
338  elements++;
339  }
340 
341  // Add name, value pair to the fixed array.
342  constant_properties->set(position++, *key);
343  constant_properties->set(position++, *value);
344  }
345 
346  constant_properties_ = constant_properties;
347  fast_elements_ =
348  (max_element_index <= 32) || ((2 * elements) >= max_element_index);
349  set_is_simple(is_simple);
350  set_depth(depth_acc);
351 }
352 
353 
354 void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
355  if (!constant_elements_.is_null()) return;
356 
357  // Allocate a fixed array to hold all the object literals.
358  Handle<JSArray> array =
359  isolate->factory()->NewJSArray(0, FAST_HOLEY_SMI_ELEMENTS);
360  JSArray::Expand(array, values()->length());
361 
362  // Fill in the literals.
363  bool is_simple = true;
364  int depth_acc = 1;
365  bool is_holey = false;
366  for (int i = 0, n = values()->length(); i < n; i++) {
367  Expression* element = values()->at(i);
368  MaterializedLiteral* m_literal = element->AsMaterializedLiteral();
369  if (m_literal != NULL) {
370  m_literal->BuildConstants(isolate);
371  if (m_literal->depth() + 1 > depth_acc) {
372  depth_acc = m_literal->depth() + 1;
373  }
374  }
375  Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
376  if (boilerplate_value->IsTheHole()) {
377  is_holey = true;
378  } else if (boilerplate_value->IsUninitialized()) {
379  is_simple = false;
381  array, i, handle(Smi::FromInt(0), isolate), SLOPPY);
382  } else {
383  JSObject::SetOwnElement(array, i, boilerplate_value, SLOPPY);
384  }
385  }
386 
387  Handle<FixedArrayBase> element_values(array->elements());
388 
389  // Simple and shallow arrays can be lazily copied, we transform the
390  // elements array to a copy-on-write array.
391  if (is_simple && depth_acc == 1 && values()->length() > 0 &&
392  array->HasFastSmiOrObjectElements()) {
393  element_values->set_map(isolate->heap()->fixed_cow_array_map());
394  }
395 
396  // Remember both the literal's constant values as well as the ElementsKind
397  // in a 2-element FixedArray.
398  Handle<FixedArray> literals = isolate->factory()->NewFixedArray(2, TENURED);
399 
400  ElementsKind kind = array->GetElementsKind();
401  kind = is_holey ? GetHoleyElementsKind(kind) : GetPackedElementsKind(kind);
402 
403  literals->set(0, Smi::FromInt(kind));
404  literals->set(1, *element_values);
405 
406  constant_elements_ = literals;
407  set_is_simple(is_simple);
408  set_depth(depth_acc);
409 }
410 
411 
413  Isolate* isolate) {
414  if (expression->AsLiteral() != NULL) {
415  return expression->AsLiteral()->value();
416  }
417  if (CompileTimeValue::IsCompileTimeValue(expression)) {
418  return CompileTimeValue::GetValue(isolate, expression);
419  }
420  return isolate->factory()->uninitialized_value();
421 }
422 
423 
425  if (IsArrayLiteral()) {
426  return AsArrayLiteral()->BuildConstantElements(isolate);
427  }
428  if (IsObjectLiteral()) {
429  return AsObjectLiteral()->BuildConstantProperties(isolate);
430  }
431  ASSERT(IsRegExpLiteral());
432  ASSERT(depth() >= 1); // Depth should be initialized.
433 }
434 
435 
436 void TargetCollector::AddTarget(Label* target, Zone* zone) {
437  // Add the label to the collector, but discard duplicates.
438  int length = targets_.length();
439  for (int i = 0; i < length; i++) {
440  if (targets_[i] == target) return;
441  }
442  targets_.Add(target, zone);
443 }
444 
445 
446 void UnaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
447  // TODO(olivf) If this Operation is used in a test context, then the
448  // expression has a ToBoolean stub and we want to collect the type
449  // information. However the GraphBuilder expects it to be on the instruction
450  // corresponding to the TestContext, therefore we have to store it here and
451  // not on the operand.
452  set_to_boolean_types(oracle->ToBooleanTypes(expression()->test_id()));
453 }
454 
455 
456 void BinaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
457  // TODO(olivf) If this Operation is used in a test context, then the right
458  // hand side has a ToBoolean stub and we want to collect the type information.
459  // However the GraphBuilder expects it to be on the instruction corresponding
460  // to the TestContext, therefore we have to store it here and not on the
461  // right hand operand.
462  set_to_boolean_types(oracle->ToBooleanTypes(right()->test_id()));
463 }
464 
465 
466 bool BinaryOperation::ResultOverwriteAllowed() {
467  switch (op_) {
468  case Token::COMMA:
469  case Token::OR:
470  case Token::AND:
471  return false;
472  case Token::BIT_OR:
473  case Token::BIT_XOR:
474  case Token::BIT_AND:
475  case Token::SHL:
476  case Token::SAR:
477  case Token::SHR:
478  case Token::ADD:
479  case Token::SUB:
480  case Token::MUL:
481  case Token::DIV:
482  case Token::MOD:
483  return true;
484  default:
485  UNREACHABLE();
486  }
487  return false;
488 }
489 
490 
491 static bool IsTypeof(Expression* expr) {
492  UnaryOperation* maybe_unary = expr->AsUnaryOperation();
493  return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF;
494 }
495 
496 
497 // Check for the pattern: typeof <expression> equals <string literal>.
498 static bool MatchLiteralCompareTypeof(Expression* left,
499  Token::Value op,
500  Expression* right,
501  Expression** expr,
502  Handle<String>* check) {
503  if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
504  *expr = left->AsUnaryOperation()->expression();
505  *check = Handle<String>::cast(right->AsLiteral()->value());
506  return true;
507  }
508  return false;
509 }
510 
511 
512 bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
513  Handle<String>* check) {
514  return MatchLiteralCompareTypeof(left_, op_, right_, expr, check) ||
515  MatchLiteralCompareTypeof(right_, op_, left_, expr, check);
516 }
517 
518 
519 static bool IsVoidOfLiteral(Expression* expr) {
520  UnaryOperation* maybe_unary = expr->AsUnaryOperation();
521  return maybe_unary != NULL &&
522  maybe_unary->op() == Token::VOID &&
523  maybe_unary->expression()->AsLiteral() != NULL;
524 }
525 
526 
527 // Check for the pattern: void <literal> equals <expression> or
528 // undefined equals <expression>
529 static bool MatchLiteralCompareUndefined(Expression* left,
530  Token::Value op,
531  Expression* right,
532  Expression** expr,
533  Isolate* isolate) {
534  if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
535  *expr = right;
536  return true;
537  }
538  if (left->IsUndefinedLiteral(isolate) && Token::IsEqualityOp(op)) {
539  *expr = right;
540  return true;
541  }
542  return false;
543 }
544 
545 
546 bool CompareOperation::IsLiteralCompareUndefined(
547  Expression** expr, Isolate* isolate) {
548  return MatchLiteralCompareUndefined(left_, op_, right_, expr, isolate) ||
549  MatchLiteralCompareUndefined(right_, op_, left_, expr, isolate);
550 }
551 
552 
553 // Check for the pattern: null equals <expression>
554 static bool MatchLiteralCompareNull(Expression* left,
555  Token::Value op,
556  Expression* right,
557  Expression** expr) {
558  if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
559  *expr = right;
560  return true;
561  }
562  return false;
563 }
564 
565 
566 bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
567  return MatchLiteralCompareNull(left_, op_, right_, expr) ||
568  MatchLiteralCompareNull(right_, op_, left_, expr);
569 }
570 
571 
572 // ----------------------------------------------------------------------------
573 // Inlining support
574 
576  return proxy()->var()->IsStackAllocated();
577 }
578 
579 bool FunctionDeclaration::IsInlineable() const {
580  return false;
581 }
582 
583 
584 // ----------------------------------------------------------------------------
585 // Recording of type feedback
586 
587 // TODO(rossberg): all RecordTypeFeedback functions should disappear
588 // once we use the common type field in the AST consistently.
589 
591  to_boolean_types_ = oracle->ToBooleanTypes(test_id());
592 }
593 
594 
595 int Call::ComputeFeedbackSlotCount(Isolate* isolate) {
596  CallType call_type = GetCallType(isolate);
597  if (call_type == LOOKUP_SLOT_CALL || call_type == OTHER_CALL) {
598  // Call only uses a slot in some cases.
599  return 1;
600  }
601 
602  return 0;
603 }
604 
605 
606 Call::CallType Call::GetCallType(Isolate* isolate) const {
607  VariableProxy* proxy = expression()->AsVariableProxy();
608  if (proxy != NULL) {
609  if (proxy->var()->is_possibly_eval(isolate)) {
610  return POSSIBLY_EVAL_CALL;
611  } else if (proxy->var()->IsUnallocated()) {
612  return GLOBAL_CALL;
613  } else if (proxy->var()->IsLookupSlot()) {
614  return LOOKUP_SLOT_CALL;
615  }
616  }
617 
618  Property* property = expression()->AsProperty();
619  return property != NULL ? PROPERTY_CALL : OTHER_CALL;
620 }
621 
622 
623 bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
624  LookupResult* lookup) {
625  target_ = Handle<JSFunction>::null();
626  cell_ = Handle<Cell>::null();
627  ASSERT(lookup->IsFound() &&
628  lookup->type() == NORMAL &&
629  lookup->holder() == *global);
630  cell_ = Handle<Cell>(global->GetPropertyCell(lookup));
631  if (cell_->value()->IsJSFunction()) {
632  Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
633  // If the function is in new space we assume it's more likely to
634  // change and thus prefer the general IC code.
635  if (!lookup->isolate()->heap()->InNewSpace(*candidate)) {
636  target_ = candidate;
637  return true;
638  }
639  }
640  return false;
641 }
642 
643 
644 void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
645  int allocation_site_feedback_slot = FLAG_pretenuring_call_new
646  ? AllocationSiteFeedbackSlot()
647  : CallNewFeedbackSlot();
648  allocation_site_ =
649  oracle->GetCallNewAllocationSite(allocation_site_feedback_slot);
650  is_monomorphic_ = oracle->CallNewIsMonomorphic(CallNewFeedbackSlot());
651  if (is_monomorphic_) {
652  target_ = oracle->GetCallNewTarget(CallNewFeedbackSlot());
653  if (!allocation_site_.is_null()) {
654  elements_kind_ = allocation_site_->GetElementsKind();
655  }
656  }
657 }
658 
659 
660 void ObjectLiteral::Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
661  TypeFeedbackId id = key()->LiteralFeedbackId();
662  SmallMapList maps;
663  oracle->CollectReceiverTypes(id, &maps);
664  receiver_type_ = maps.length() == 1 ? maps.at(0)
665  : Handle<Map>::null();
666 }
667 
668 
669 // ----------------------------------------------------------------------------
670 // Implementation of AstVisitor
671 
672 void AstVisitor::VisitDeclarations(ZoneList<Declaration*>* declarations) {
673  for (int i = 0; i < declarations->length(); i++) {
674  Visit(declarations->at(i));
675  }
676 }
677 
678 
679 void AstVisitor::VisitStatements(ZoneList<Statement*>* statements) {
680  for (int i = 0; i < statements->length(); i++) {
681  Statement* stmt = statements->at(i);
682  Visit(stmt);
683  if (stmt->IsJump()) break;
684  }
685 }
686 
687 
688 void AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) {
689  for (int i = 0; i < expressions->length(); i++) {
690  // The variable statement visiting code may pass NULL expressions
691  // to this code. Maybe this should be handled by introducing an
692  // undefined expression or literal? Revisit this code if this
693  // changes
694  Expression* expression = expressions->at(i);
695  if (expression != NULL) Visit(expression);
696  }
697 }
698 
699 
700 // ----------------------------------------------------------------------------
701 // Regular expressions
702 
703 #define MAKE_ACCEPT(Name) \
704  void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) { \
705  return visitor->Visit##Name(this, data); \
706  }
708 #undef MAKE_ACCEPT
709 
710 #define MAKE_TYPE_CASE(Name) \
711  RegExp##Name* RegExpTree::As##Name() { \
712  return NULL; \
713  } \
714  bool RegExpTree::Is##Name() { return false; }
716 #undef MAKE_TYPE_CASE
717 
718 #define MAKE_TYPE_CASE(Name) \
719  RegExp##Name* RegExp##Name::As##Name() { \
720  return this; \
721  } \
722  bool RegExp##Name::Is##Name() { return true; }
724 #undef MAKE_TYPE_CASE
725 
726 
727 static Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) {
728  Interval result = Interval::Empty();
729  for (int i = 0; i < children->length(); i++)
730  result = result.Union(children->at(i)->CaptureRegisters());
731  return result;
732 }
733 
734 
735 Interval RegExpAlternative::CaptureRegisters() {
736  return ListCaptureRegisters(nodes());
737 }
738 
739 
740 Interval RegExpDisjunction::CaptureRegisters() {
741  return ListCaptureRegisters(alternatives());
742 }
743 
744 
745 Interval RegExpLookahead::CaptureRegisters() {
746  return body()->CaptureRegisters();
747 }
748 
749 
750 Interval RegExpCapture::CaptureRegisters() {
751  Interval self(StartRegister(index()), EndRegister(index()));
752  return self.Union(body()->CaptureRegisters());
753 }
754 
755 
756 Interval RegExpQuantifier::CaptureRegisters() {
757  return body()->CaptureRegisters();
758 }
759 
760 
761 bool RegExpAssertion::IsAnchoredAtStart() {
762  return assertion_type() == RegExpAssertion::START_OF_INPUT;
763 }
764 
765 
766 bool RegExpAssertion::IsAnchoredAtEnd() {
767  return assertion_type() == RegExpAssertion::END_OF_INPUT;
768 }
769 
770 
771 bool RegExpAlternative::IsAnchoredAtStart() {
772  ZoneList<RegExpTree*>* nodes = this->nodes();
773  for (int i = 0; i < nodes->length(); i++) {
774  RegExpTree* node = nodes->at(i);
775  if (node->IsAnchoredAtStart()) { return true; }
776  if (node->max_match() > 0) { return false; }
777  }
778  return false;
779 }
780 
781 
782 bool RegExpAlternative::IsAnchoredAtEnd() {
783  ZoneList<RegExpTree*>* nodes = this->nodes();
784  for (int i = nodes->length() - 1; i >= 0; i--) {
785  RegExpTree* node = nodes->at(i);
786  if (node->IsAnchoredAtEnd()) { return true; }
787  if (node->max_match() > 0) { return false; }
788  }
789  return false;
790 }
791 
792 
793 bool RegExpDisjunction::IsAnchoredAtStart() {
794  ZoneList<RegExpTree*>* alternatives = this->alternatives();
795  for (int i = 0; i < alternatives->length(); i++) {
796  if (!alternatives->at(i)->IsAnchoredAtStart())
797  return false;
798  }
799  return true;
800 }
801 
802 
803 bool RegExpDisjunction::IsAnchoredAtEnd() {
804  ZoneList<RegExpTree*>* alternatives = this->alternatives();
805  for (int i = 0; i < alternatives->length(); i++) {
806  if (!alternatives->at(i)->IsAnchoredAtEnd())
807  return false;
808  }
809  return true;
810 }
811 
812 
813 bool RegExpLookahead::IsAnchoredAtStart() {
814  return is_positive() && body()->IsAnchoredAtStart();
815 }
816 
817 
818 bool RegExpCapture::IsAnchoredAtStart() {
819  return body()->IsAnchoredAtStart();
820 }
821 
822 
823 bool RegExpCapture::IsAnchoredAtEnd() {
824  return body()->IsAnchoredAtEnd();
825 }
826 
827 
828 // Convert regular expression trees to a simple sexp representation.
829 // This representation should be different from the input grammar
830 // in as many cases as possible, to make it more difficult for incorrect
831 // parses to look as correct ones which is likely if the input and
832 // output formats are alike.
833 class RegExpUnparser V8_FINAL : public RegExpVisitor {
834  public:
835  explicit RegExpUnparser(Zone* zone);
836  void VisitCharacterRange(CharacterRange that);
838 #define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, \
839  void* data) V8_OVERRIDE;
841 #undef MAKE_CASE
842  private:
843  StringStream* stream() { return &stream_; }
844  HeapStringAllocator alloc_;
845  StringStream stream_;
846  Zone* zone_;
847 };
848 
849 
850 RegExpUnparser::RegExpUnparser(Zone* zone) : stream_(&alloc_), zone_(zone) {
851 }
852 
853 
854 void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) {
855  stream()->Add("(|");
856  for (int i = 0; i < that->alternatives()->length(); i++) {
857  stream()->Add(" ");
858  that->alternatives()->at(i)->Accept(this, data);
859  }
860  stream()->Add(")");
861  return NULL;
862 }
863 
864 
865 void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) {
866  stream()->Add("(:");
867  for (int i = 0; i < that->nodes()->length(); i++) {
868  stream()->Add(" ");
869  that->nodes()->at(i)->Accept(this, data);
870  }
871  stream()->Add(")");
872  return NULL;
873 }
874 
875 
876 void RegExpUnparser::VisitCharacterRange(CharacterRange that) {
877  stream()->Add("%k", that.from());
878  if (!that.IsSingleton()) {
879  stream()->Add("-%k", that.to());
880  }
881 }
882 
883 
884 
885 void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that,
886  void* data) {
887  if (that->is_negated())
888  stream()->Add("^");
889  stream()->Add("[");
890  for (int i = 0; i < that->ranges(zone_)->length(); i++) {
891  if (i > 0) stream()->Add(" ");
892  VisitCharacterRange(that->ranges(zone_)->at(i));
893  }
894  stream()->Add("]");
895  return NULL;
896 }
897 
898 
899 void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
900  switch (that->assertion_type()) {
901  case RegExpAssertion::START_OF_INPUT:
902  stream()->Add("@^i");
903  break;
904  case RegExpAssertion::END_OF_INPUT:
905  stream()->Add("@$i");
906  break;
907  case RegExpAssertion::START_OF_LINE:
908  stream()->Add("@^l");
909  break;
910  case RegExpAssertion::END_OF_LINE:
911  stream()->Add("@$l");
912  break;
913  case RegExpAssertion::BOUNDARY:
914  stream()->Add("@b");
915  break;
916  case RegExpAssertion::NON_BOUNDARY:
917  stream()->Add("@B");
918  break;
919  }
920  return NULL;
921 }
922 
923 
924 void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
925  stream()->Add("'");
926  Vector<const uc16> chardata = that->data();
927  for (int i = 0; i < chardata.length(); i++) {
928  stream()->Add("%k", chardata[i]);
929  }
930  stream()->Add("'");
931  return NULL;
932 }
933 
934 
935 void* RegExpUnparser::VisitText(RegExpText* that, void* data) {
936  if (that->elements()->length() == 1) {
937  that->elements()->at(0).tree()->Accept(this, data);
938  } else {
939  stream()->Add("(!");
940  for (int i = 0; i < that->elements()->length(); i++) {
941  stream()->Add(" ");
942  that->elements()->at(i).tree()->Accept(this, data);
943  }
944  stream()->Add(")");
945  }
946  return NULL;
947 }
948 
949 
950 void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) {
951  stream()->Add("(# %i ", that->min());
952  if (that->max() == RegExpTree::kInfinity) {
953  stream()->Add("- ");
954  } else {
955  stream()->Add("%i ", that->max());
956  }
957  stream()->Add(that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n ");
958  that->body()->Accept(this, data);
959  stream()->Add(")");
960  return NULL;
961 }
962 
963 
964 void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
965  stream()->Add("(^ ");
966  that->body()->Accept(this, data);
967  stream()->Add(")");
968  return NULL;
969 }
970 
971 
972 void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
973  stream()->Add("(-> ");
974  stream()->Add(that->is_positive() ? "+ " : "- ");
975  that->body()->Accept(this, data);
976  stream()->Add(")");
977  return NULL;
978 }
979 
980 
981 void* RegExpUnparser::VisitBackReference(RegExpBackReference* that,
982  void* data) {
983  stream()->Add("(<- %i)", that->index());
984  return NULL;
985 }
986 
987 
988 void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) {
989  stream()->Put('%');
990  return NULL;
991 }
992 
993 
994 SmartArrayPointer<const char> RegExpTree::ToString(Zone* zone) {
995  RegExpUnparser unparser(zone);
996  Accept(&unparser, NULL);
997  return unparser.ToString();
998 }
999 
1000 
1001 RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
1002  : alternatives_(alternatives) {
1003  ASSERT(alternatives->length() > 1);
1004  RegExpTree* first_alternative = alternatives->at(0);
1005  min_match_ = first_alternative->min_match();
1006  max_match_ = first_alternative->max_match();
1007  for (int i = 1; i < alternatives->length(); i++) {
1008  RegExpTree* alternative = alternatives->at(i);
1009  min_match_ = Min(min_match_, alternative->min_match());
1010  max_match_ = Max(max_match_, alternative->max_match());
1011  }
1012 }
1013 
1014 
1015 static int IncreaseBy(int previous, int increase) {
1016  if (RegExpTree::kInfinity - previous < increase) {
1017  return RegExpTree::kInfinity;
1018  } else {
1019  return previous + increase;
1020  }
1021 }
1022 
1023 RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
1024  : nodes_(nodes) {
1025  ASSERT(nodes->length() > 1);
1026  min_match_ = 0;
1027  max_match_ = 0;
1028  for (int i = 0; i < nodes->length(); i++) {
1029  RegExpTree* node = nodes->at(i);
1030  int node_min_match = node->min_match();
1031  min_match_ = IncreaseBy(min_match_, node_min_match);
1032  int node_max_match = node->max_match();
1033  max_match_ = IncreaseBy(max_match_, node_max_match);
1034  }
1035 }
1036 
1037 
1038 CaseClause::CaseClause(Zone* zone,
1039  Expression* label,
1040  ZoneList<Statement*>* statements,
1041  int pos)
1042  : Expression(zone, pos),
1043  label_(label),
1044  statements_(statements),
1045  compare_type_(Type::None(zone)),
1046  compare_id_(AstNode::GetNextId(zone)),
1047  entry_id_(AstNode::GetNextId(zone)) {
1048 }
1049 
1050 
1051 #define REGULAR_NODE(NodeType) \
1052  void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1053  increase_node_count(); \
1054  }
1055 #define REGULAR_NODE_WITH_FEEDBACK_SLOTS(NodeType) \
1056  void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1057  increase_node_count(); \
1058  add_slot_node(node); \
1059  }
1060 #define DONT_OPTIMIZE_NODE(NodeType) \
1061  void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1062  increase_node_count(); \
1063  set_dont_optimize_reason(k##NodeType); \
1064  add_flag(kDontInline); \
1065  add_flag(kDontSelfOptimize); \
1066  }
1067 #define DONT_SELFOPTIMIZE_NODE(NodeType) \
1068  void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1069  increase_node_count(); \
1070  add_flag(kDontSelfOptimize); \
1071  }
1072 #define DONT_SELFOPTIMIZE_NODE_WITH_FEEDBACK_SLOTS(NodeType) \
1073  void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1074  increase_node_count(); \
1075  add_slot_node(node); \
1076  add_flag(kDontSelfOptimize); \
1077  }
1078 #define DONT_CACHE_NODE(NodeType) \
1079  void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1080  increase_node_count(); \
1081  set_dont_optimize_reason(k##NodeType); \
1082  add_flag(kDontInline); \
1083  add_flag(kDontSelfOptimize); \
1084  add_flag(kDontCache); \
1085  }
1086 
1087 REGULAR_NODE(VariableDeclaration)
1088 REGULAR_NODE(FunctionDeclaration)
1090 REGULAR_NODE(ExpressionStatement)
1091 REGULAR_NODE(EmptyStatement)
1092 REGULAR_NODE(IfStatement)
1093 REGULAR_NODE(ContinueStatement)
1094 REGULAR_NODE(BreakStatement)
1095 REGULAR_NODE(ReturnStatement)
1096 REGULAR_NODE(SwitchStatement)
1097 REGULAR_NODE(CaseClause)
1098 REGULAR_NODE(Conditional)
1099 REGULAR_NODE(Literal)
1100 REGULAR_NODE(ArrayLiteral)
1101 REGULAR_NODE(ObjectLiteral)
1102 REGULAR_NODE(RegExpLiteral)
1103 REGULAR_NODE(FunctionLiteral)
1104 REGULAR_NODE(Assignment)
1105 REGULAR_NODE(Throw)
1106 REGULAR_NODE(Property)
1107 REGULAR_NODE(UnaryOperation)
1108 REGULAR_NODE(CountOperation)
1109 REGULAR_NODE(BinaryOperation)
1110 REGULAR_NODE(CompareOperation)
1111 REGULAR_NODE(ThisFunction)
1114 // In theory, for VariableProxy we'd have to add:
1115 // if (node->var()->IsLookupSlot()) add_flag(kDontInline);
1116 // But node->var() is usually not bound yet at VariableProxy creation time, and
1117 // LOOKUP variables only result from constructs that cannot be inlined anyway.
1118 REGULAR_NODE(VariableProxy)
1119 
1120 // We currently do not optimize any modules.
1121 DONT_OPTIMIZE_NODE(ModuleDeclaration)
1122 DONT_OPTIMIZE_NODE(ImportDeclaration)
1123 DONT_OPTIMIZE_NODE(ExportDeclaration)
1124 DONT_OPTIMIZE_NODE(ModuleVariable)
1125 DONT_OPTIMIZE_NODE(ModulePath)
1126 DONT_OPTIMIZE_NODE(ModuleUrl)
1127 DONT_OPTIMIZE_NODE(ModuleStatement)
1128 DONT_OPTIMIZE_NODE(Yield)
1129 DONT_OPTIMIZE_NODE(WithStatement)
1130 DONT_OPTIMIZE_NODE(TryCatchStatement)
1131 DONT_OPTIMIZE_NODE(TryFinallyStatement)
1132 DONT_OPTIMIZE_NODE(DebuggerStatement)
1133 DONT_OPTIMIZE_NODE(NativeFunctionLiteral)
1134 
1135 DONT_SELFOPTIMIZE_NODE(DoWhileStatement)
1136 DONT_SELFOPTIMIZE_NODE(WhileStatement)
1137 DONT_SELFOPTIMIZE_NODE(ForStatement)
1139 DONT_SELFOPTIMIZE_NODE(ForOfStatement)
1140 
1141 DONT_CACHE_NODE(ModuleLiteral)
1142 
1143 
1144 void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
1145  increase_node_count();
1146  if (node->is_jsruntime()) {
1147  // Don't try to inline JS runtime calls because we don't (currently) even
1148  // optimize them.
1149  add_flag(kDontInline);
1150  } else if (node->function()->intrinsic_type == Runtime::INLINE &&
1151  (node->name()->IsOneByteEqualTo(
1152  STATIC_ASCII_VECTOR("_ArgumentsLength")) ||
1153  node->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_Arguments")))) {
1154  // Don't inline the %_ArgumentsLength or %_Arguments because their
1155  // implementation will not work. There is no stack frame to get them
1156  // from.
1157  add_flag(kDontInline);
1158  }
1159 }
1160 
1161 #undef REGULAR_NODE
1162 #undef DONT_OPTIMIZE_NODE
1163 #undef DONT_SELFOPTIMIZE_NODE
1164 #undef DONT_CACHE_NODE
1165 
1166 
1167 Handle<String> Literal::ToString() {
1168  if (value_->IsString()) return Handle<String>::cast(value_);
1169  ASSERT(value_->IsNumber());
1170  char arr[100];
1171  Vector<char> buffer(arr, ARRAY_SIZE(arr));
1172  const char* str;
1173  if (value_->IsSmi()) {
1174  // Optimization only, the heap number case would subsume this.
1175  OS::SNPrintF(buffer, "%d", Smi::cast(*value_)->value());
1176  str = arr;
1177  } else {
1178  str = DoubleToCString(value_->Number(), buffer);
1179  }
1180  return isolate_->factory()->NewStringFromAscii(CStrVector(str));
1181 }
1182 
1183 
1184 } } // namespace v8::internal
bool IsStringLiteral()
Definition: ast.cc:64
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
TypeFeedbackId test_id() const
Definition: ast.h:378
#define MAKE_TYPE_CASE(Name)
Definition: ast.cc:718
#define FOR_EACH_REG_EXP_TREE_TYPE(VISIT)
Definition: jsregexp.h:410
byte ToBooleanTypes(TypeFeedbackId id)
Definition: type-info.cc:413
ElementsKind GetPackedElementsKind(ElementsKind holey_kind)
#define DONT_SELFOPTIMIZE_NODE(NodeType)
Definition: ast.cc:1067
#define DONT_SELFOPTIMIZE_NODE_WITH_FEEDBACK_SLOTS(NodeType)
Definition: ast.cc:1072
static String * cast(Object *obj)
void BuildConstants(Isolate *isolate)
Definition: ast.cc:424
static Smi * FromInt(int value)
Definition: objects-inl.h:1209
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
T Max(T a, T b)
Definition: utils.h:227
kSerializedDataOffset Object
Definition: objects-inl.h:5016
TypeImpl< ZoneTypeConfig > Type
Location location() const
Definition: variables.h:146
#define DECL_ACCEPT(type)
Definition: ast.cc:49
#define ASSERT(condition)
Definition: checks.h:329
static bool IsCompileTimeValue(Expression *expression)
Definition: parser.cc:3090
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including on console Map counters to a file Enable debugger compile events enable GDBJIT interface(disables compacting GC)") DEFINE_bool(gdbjit_full
static SharedFunctionInfo * cast(Object *obj)
Factory * factory()
Definition: isolate.h:995
static Interval Empty()
Definition: jsregexp.h:729
#define REGULAR_NODE_WITH_FEEDBACK_SLOTS(NodeType)
Definition: ast.cc:1055
static Smi * cast(Object *object)
virtual bool IsInlineable() const
Definition: ast.cc:575
V8_INLINE bool IsNull() const
Definition: v8.h:6247
#define UNREACHABLE()
Definition: checks.h:52
VariableProxy * proxy() const
Definition: ast.h:486
#define REGULAR_NODE(NodeType)
Definition: ast.cc:1051
static const int kInfinity
Definition: ast.h:2502
void check(i::Vector< const uint8_t > string)
#define DONT_CACHE_NODE(NodeType)
Definition: ast.cc:1078
const char * DoubleToCString(double v, Vector< char > buffer)
Definition: conversions.cc:81
virtual int min_match()=0
static Handle< FixedArray > GetValue(Isolate *isolate, Expression *expression)
Definition: parser.cc:3097
Handle< Object > GetBoilerplateValue(Expression *expression, Isolate *isolate)
Definition: ast.cc:412
static Handle< Object > SetOwnElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, StrictMode strict_mode)
Definition: objects.cc:12401
#define MAKE_CASE(Name)
Definition: ast.cc:838
bool IsUndefinedLiteral(Isolate *isolate)
Definition: ast.cc:74
#define COMMA
Definition: flags.h:101
static bool IsEqualityOp(Value op)
Definition: token.h:228
#define STATIC_ASCII_VECTOR(x)
Definition: utils.h:570
Vector< const char > CStrVector(const char *data)
Definition: utils.h:574
#define AST_NODE_LIST(V)
Definition: ast.h:121
V8_INLINE bool IsString() const
Definition: v8.h:6265
Definition: v8.h:2107
static int SNPrintF(Vector< char > str, const char *format,...)
virtual void RecordToBooleanTypeFeedback(TypeFeedbackOracle *oracle)
Definition: ast.cc:590
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:103
static Handle< T > null()
Definition: handles.h:80
static void Expand(Handle< JSArray > array, int minimum_size_of_backing_fixed_array)
Definition: objects.cc:11251
StringCharacterStream *const stream_
HeapObject * obj
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric literals(0o77, 0b11)") DEFINE_bool(harmony_strings
#define MAKE_ACCEPT(Name)
Definition: ast.cc:703
SmartArrayPointer< const char > ToString()
Definition: ast.cc:837
T Min(T a, T b)
Definition: utils.h:234
virtual int max_match()=0
TemplateHashMapImpl< ZoneAllocationPolicy > ZoneHashMap
Definition: zone.h:267
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
#define VOID
bool IsNullLiteral()
Definition: ast.cc:69
#define DONT_OPTIMIZE_NODE(NodeType)
Definition: ast.cc:1060
#define ARRAY_SIZE(a)
Definition: globals.h:333
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
static JSFunction * cast(Object *obj)