23 #define __ ACCESS_MASM(masm_)
28 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
30 info_emitted_ =
false;
35 DCHECK(patch_site_.is_bound() == info_emitted_);
38 void EmitJumpIfNotSmi(Register reg,
40 Label::Distance near_jump = Label::kFar) {
45 void EmitJumpIfSmi(Register reg,
47 Label::Distance near_jump = Label::kFar) {
49 EmitJump(
carry, target, near_jump);
52 void EmitPatchInfo() {
53 if (patch_site_.is_bound()) {
54 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
55 DCHECK(is_uint8(delta_to_patch_site));
56 __ testl(
rax, Immediate(delta_to_patch_site));
67 void EmitJump(
Condition cc, Label* target, Label::Distance near_jump) {
68 DCHECK(!patch_site_.is_bound() && !info_emitted_);
70 __ bind(&patch_site_);
71 __ j(
cc, target, near_jump);
74 MacroAssembler* masm_;
96 CompilationInfo* info =
info_;
98 isolate()->factory()->NewFixedArray(
function()->handler_count(),
TENURED);
101 Handle<Smi>(
Smi::FromInt(FLAG_interrupt_budget), isolate()));
103 Comment cmnt(
masm_,
"[ function compiled by full code generator");
108 if (strlen(FLAG_stop_at) > 0 &&
109 info->function()->name()->IsUtf8EqualTo(
CStrVector(FLAG_stop_at))) {
117 if (info->strict_mode() ==
SLOPPY && !info->is_native()) {
120 StackArgumentsAccessor args(
rsp, info->scope()->num_parameters());
121 __ movp(
rcx, args.GetReceiverOperand());
123 __ CompareRoot(
rcx, Heap::kUndefinedValueRootIndex);
129 __ movp(args.GetReceiverOperand(),
rcx);
137 FrameScope frame_scope(
masm_, StackFrame::MANUAL);
140 __ Prologue(info->IsCodePreAgingActive());
143 { Comment cmnt(
masm_,
"[ Allocate locals");
144 int locals_count = info->scope()->num_stack_slots();
146 DCHECK(!info->function()->is_generator() || locals_count == 0);
147 if (locals_count == 1) {
148 __ PushRoot(Heap::kUndefinedValueRootIndex);
149 }
else if (locals_count > 1) {
150 if (locals_count >= 128) {
154 __ CompareRoot(
rcx, Heap::kRealStackLimitRootIndex);
159 __ LoadRoot(
rdx, Heap::kUndefinedValueRootIndex);
160 const int kMaxPushes = 32;
161 if (locals_count >= kMaxPushes) {
162 int loop_iterations = locals_count / kMaxPushes;
163 __ movp(
rcx, Immediate(loop_iterations));
165 __ bind(&loop_header);
167 for (
int i = 0;
i < kMaxPushes;
i++) {
174 int remaining = locals_count % kMaxPushes;
176 for (
int i = 0;
i < remaining;
i++) {
182 bool function_in_register =
true;
186 if (heap_slots > 0) {
187 Comment cmnt(
masm_,
"[ Allocate context");
188 bool need_write_barrier =
true;
190 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
192 __ Push(info->scope()->GetScopeInfo());
193 __ CallRuntime(Runtime::kNewGlobalContext, 2);
194 }
else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
195 FastNewContextStub stub(isolate(), heap_slots);
198 need_write_barrier =
false;
201 __ CallRuntime(Runtime::kNewFunctionContext, 1);
203 function_in_register =
false;
210 int num_parameters = info->scope()->num_parameters();
211 for (
int i = 0;
i < num_parameters;
i++) {
213 if (var->IsContextSlot()) {
217 __ movp(
rax, Operand(
rbp, parameter_offset));
220 __ movp(Operand(
rsi, context_offset),
rax);
222 if (need_write_barrier) {
223 __ RecordWriteContextSlot(
225 }
else if (FLAG_debug_code) {
227 __ JumpIfInNewSpace(
rsi,
rax, &done, Label::kNear);
228 __ Abort(kExpectedNewSpaceObject);
237 if (arguments !=
NULL) {
240 Comment cmnt(
masm_,
"[ Allocate arguments object");
241 if (function_in_register) {
247 int num_parameters = info->scope()->num_parameters();
265 ArgumentsAccessStub stub(isolate(), type);
272 __ CallRuntime(Runtime::kTraceEnter, 0);
277 if (
scope()->HasIllegalRedeclaration()) {
278 Comment cmnt(
masm_,
"[ Declarations");
283 { Comment cmnt(
masm_,
"[ Declarations");
286 if (
scope()->is_function_scope() &&
scope()->
function() !=
NULL) {
291 VisitVariableDeclaration(
function);
296 { Comment cmnt(
masm_,
"[ Stack check");
299 __ CompareRoot(
rsp, Heap::kStackLimitRootIndex);
305 { Comment cmnt(
masm_,
"[ Body");
307 VisitStatements(
function()->body());
314 { Comment cmnt(
masm_,
"[ return <undefined>;");
315 __ LoadRoot(
rax, Heap::kUndefinedValueRootIndex);
334 int reset_value = FLAG_interrupt_budget;
345 Label* back_edge_target) {
346 Comment cmnt(
masm_,
"[ Back edge bookkeeping");
349 DCHECK(back_edge_target->is_bound());
352 Max(1, distance / kCodeSizeMultiplier));
357 PredictableCodeSizeScope predictible_code_size_scope(
masm_, kJnsOffset);
358 DontEmitDebugCodeScope dont_emit_debug_code_scope(
masm_);
379 Comment cmnt(
masm_,
"[ Return sequence");
386 __ CallRuntime(Runtime::kTraceExit, 1);
391 weight = FLAG_interrupt_budget / FLAG_self_opt_count;
395 Max(1, distance / kCodeSizeMultiplier));
401 __ call(isolate()->builtins()->InterruptCheck(),
408 Label check_exit_codesize;
420 __ Ret(arguments_bytes,
rcx);
427 for (
int i = 0;
i < kPadding; ++
i) {
441 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
446 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
452 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
460 codegen()->PrepareForBailoutBeforeSplit(condition(),
false,
NULL,
NULL);
461 codegen()->DoTest(
this);
482 codegen()->PrepareForBailoutBeforeSplit(condition(),
486 if (index == Heap::kUndefinedValueRootIndex ||
487 index == Heap::kNullValueRootIndex ||
488 index == Heap::kFalseValueRootIndex) {
489 if (false_label_ != fall_through_)
__ jmp(false_label_);
490 }
else if (index == Heap::kTrueValueRootIndex) {
491 if (true_label_ != fall_through_)
__ jmp(true_label_);
494 codegen()->DoTest(
this);
504 Handle<Object> lit)
const {
515 __ SafePush(Smi::cast(*lit));
523 codegen()->PrepareForBailoutBeforeSplit(condition(),
527 DCHECK(!lit->IsUndetectableObject());
528 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
529 if (false_label_ != fall_through_)
__ jmp(false_label_);
530 }
else if (lit->IsTrue() || lit->IsJSObject()) {
531 if (true_label_ != fall_through_)
__ jmp(true_label_);
532 }
else if (lit->IsString()) {
533 if (String::cast(*lit)->length() == 0) {
534 if (false_label_ != fall_through_)
__ jmp(false_label_);
536 if (true_label_ != fall_through_)
__ jmp(true_label_);
538 }
else if (lit->IsSmi()) {
539 if (Smi::cast(*lit)->value() == 0) {
540 if (false_label_ != fall_through_)
__ jmp(false_label_);
542 if (true_label_ != fall_through_)
__ jmp(true_label_);
547 codegen()->DoTest(
this);
553 Register reg)
const {
561 Register reg)
const {
569 Register reg)
const {
571 if (count > 1)
__ Drop(count - 1);
572 __ movp(Operand(
rsp, 0), reg);
577 Register reg)
const {
582 codegen()->PrepareForBailoutBeforeSplit(condition(),
false,
NULL,
NULL);
583 codegen()->DoTest(
this);
588 Label* materialize_false)
const {
589 DCHECK(materialize_true == materialize_false);
590 __ bind(materialize_true);
595 Label* materialize_true,
596 Label* materialize_false)
const {
598 __ bind(materialize_true);
600 __ jmp(&done, Label::kNear);
601 __ bind(materialize_false);
608 Label* materialize_true,
609 Label* materialize_false)
const {
611 __ bind(materialize_true);
612 __ Push(isolate()->factory()->true_value());
613 __ jmp(&done, Label::kNear);
614 __ bind(materialize_false);
615 __ Push(isolate()->factory()->false_value());
621 Label* materialize_false)
const {
622 DCHECK(materialize_true == true_label_);
623 DCHECK(materialize_false == false_label_);
633 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
640 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
641 __ PushRoot(value_root_index);
646 codegen()->PrepareForBailoutBeforeSplit(condition(),
651 if (true_label_ != fall_through_)
__ jmp(true_label_);
653 if (false_label_ != fall_through_)
__ jmp(false_label_);
661 Label* fall_through) {
663 CallIC(ic, condition->test_id());
673 Label* fall_through) {
674 if (if_false == fall_through) {
676 }
else if (if_true == fall_through) {
686 DCHECK(var->IsStackAllocated());
690 if (var->IsParameter()) {
696 return Operand(
rbp, offset);
701 DCHECK(var->IsContextSlot() || var->IsStackAllocated());
702 if (var->IsContextSlot()) {
704 __ LoadContext(scratch, context_chain_length);
713 DCHECK(var->IsContextSlot() || var->IsStackAllocated());
715 __ movp(dest, location);
723 DCHECK(var->IsContextSlot() || var->IsStackAllocated());
724 DCHECK(!scratch0.is(src));
725 DCHECK(!scratch0.is(scratch1));
726 DCHECK(!scratch1.is(src));
728 __ movp(location, src);
731 if (var->IsContextSlot()) {
739 bool should_normalize,
748 if (should_normalize)
__ jmp(&skip, Label::kNear);
750 if (should_normalize) {
751 __ CompareRoot(
rax, Heap::kTrueValueRootIndex);
764 __ CompareRoot(
rbx, Heap::kWithContextMapRootIndex);
766 __ CompareRoot(
rbx, Heap::kCatchContextMapRootIndex);
772 void FullCodeGenerator::VisitVariableDeclaration(
773 VariableDeclaration* declaration) {
777 VariableProxy* proxy = declaration->proxy();
779 Variable* variable = proxy->var();
781 switch (variable->location()) {
783 globals_->Add(variable->name(), zone());
784 globals_->Add(variable->binding_needs_init()
785 ? isolate()->factory()->the_hole_value()
786 : isolate()->factory()->undefined_value(),
793 Comment cmnt(
masm_,
"[ VariableDeclaration");
801 Comment cmnt(
masm_,
"[ VariableDeclaration");
811 Comment cmnt(
masm_,
"[ VariableDeclaration");
813 __ Push(variable->name());
824 __ PushRoot(Heap::kTheHoleValueRootIndex);
828 __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
835 void FullCodeGenerator::VisitFunctionDeclaration(
836 FunctionDeclaration* declaration) {
837 VariableProxy* proxy = declaration->proxy();
838 Variable* variable = proxy->var();
839 switch (variable->location()) {
841 globals_->Add(variable->name(), zone());
842 Handle<SharedFunctionInfo>
function =
845 if (
function.is_null())
return SetStackOverflow();
852 Comment cmnt(
masm_,
"[ FunctionDeclaration");
859 Comment cmnt(
masm_,
"[ FunctionDeclaration");
865 __ RecordWriteContextSlot(
rsi,
877 Comment cmnt(
masm_,
"[ FunctionDeclaration");
879 __ Push(variable->name());
882 __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
889 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
890 Variable* variable = declaration->proxy()->var();
892 DCHECK(variable->interface()->IsFrozen());
894 Comment cmnt(
masm_,
"[ ModuleDeclaration");
905 __ RecordWriteContextSlot(
rsi,
915 Visit(declaration->module());
919 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
920 VariableProxy* proxy = declaration->proxy();
921 Variable* variable = proxy->var();
922 switch (variable->location()) {
928 Comment cmnt(
masm_,
"[ ImportDeclaration");
942 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
952 __ CallRuntime(Runtime::kDeclareGlobals, 3);
960 __ CallRuntime(Runtime::kDeclareModules, 1);
965 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
966 Comment cmnt(
masm_,
"[ SwitchStatement");
967 Breakable nested_statement(
this, stmt);
974 ZoneList<CaseClause*>* clauses = stmt->cases();
975 CaseClause* default_clause =
NULL;
979 for (
int i = 0;
i < clauses->length();
i++) {
980 CaseClause* clause = clauses->at(
i);
981 clause->body_target()->Unuse();
984 if (clause->is_default()) {
985 default_clause = clause;
989 Comment cmnt(
masm_,
"[ Case comparison");
999 JumpPatchSite patch_site(
masm_);
1000 if (inline_smi_code) {
1004 patch_site.EmitJumpIfNotSmi(
rcx, &slow_case, Label::kNear);
1009 __ jmp(clause->body_target());
1010 __ bind(&slow_case);
1016 CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
1017 CallIC(ic, clause->CompareId());
1018 patch_site.EmitPatchInfo();
1021 __ jmp(&skip, Label::kNear);
1023 __ CompareRoot(
rax, Heap::kTrueValueRootIndex);
1026 __ jmp(clause->body_target());
1032 __ jmp(clause->body_target());
1037 __ bind(&next_test);
1039 if (default_clause ==
NULL) {
1040 __ jmp(nested_statement.break_label());
1042 __ jmp(default_clause->body_target());
1046 for (
int i = 0;
i < clauses->length();
i++) {
1047 Comment cmnt(
masm_,
"[ Case body");
1048 CaseClause* clause = clauses->at(
i);
1049 __ bind(clause->body_target());
1051 VisitStatements(clause->statements());
1054 __ bind(nested_statement.break_label());
1059 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1060 Comment cmnt(
masm_,
"[ ForInStatement");
1061 int slot = stmt->ForInFeedbackSlot();
1065 ForIn loop_statement(
this, stmt);
1071 __ CompareRoot(
rax, Heap::kUndefinedValueRootIndex);
1073 Register null_value =
rdi;
1074 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
1075 __ cmpp(
rax, null_value);
1081 Label convert, done_convert;
1082 __ JumpIfSmi(
rax, &convert);
1088 __ bind(&done_convert);
1101 __ CheckEnumCache(null_value, &call_runtime);
1107 __ jmp(&use_cache, Label::kNear);
1110 __ bind(&call_runtime);
1112 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1119 Heap::kMetaMapRootIndex);
1123 __ bind(&use_cache);
1125 Label no_descriptors;
1131 __ LoadInstanceDescriptors(
rax,
rcx);
1142 __ bind(&no_descriptors);
1148 __ bind(&fixed_array);
1160 __ bind(&non_proxy);
1191 __ j(
equal, &update_each, Label::kNear);
1196 __ j(
equal, &update_each, Label::kNear);
1205 __ j(
equal, loop_statement.continue_label());
1210 __ bind(&update_each);
1213 { EffectContext
context(
this);
1218 Visit(stmt->body());
1222 __ bind(loop_statement.continue_label());
1229 __ bind(loop_statement.break_label());
1239 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1240 Comment cmnt(
masm_,
"[ ForOfStatement");
1243 Iteration loop_statement(
this, stmt);
1250 __ bind(loop_statement.continue_label());
1256 Label result_not_done;
1258 loop_statement.break_label(),
1261 __ bind(&result_not_done);
1267 Visit(stmt->body());
1272 __ jmp(loop_statement.continue_label());
1276 __ bind(loop_statement.break_label());
1289 if (!FLAG_always_opt &&
1290 !FLAG_prepare_always_opt &&
1292 scope()->is_function_scope() &&
1293 info->num_literals() == 0) {
1294 FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
1301 ? isolate()->factory()->true_value()
1302 : isolate()->factory()->false_value());
1303 __ CallRuntime(Runtime::kNewClosure, 3);
1309 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
1310 Comment cmnt(
masm_,
"[ VariableProxy");
1316 Comment cnmt(
masm_,
"[ SuperReference ");
1321 Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
1326 __ Cmp(
rax, isolate()->factory()->undefined_value());
1329 __ CallRuntime(Runtime::kThrowNonMethodError, 0);
1338 Register temp =
rdx;
1342 if (s->num_heap_slots() > 0) {
1343 if (s->calls_sloppy_eval()) {
1357 if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope())
break;
1358 s = s->outer_scope();
1361 if (s !=
NULL && s->is_eval_scope()) {
1373 __ j(
equal, &fast, Label::kNear);
1387 if (FLAG_vector_ics) {
1401 DCHECK(var->IsContextSlot());
1403 Register temp =
rbx;
1406 if (s->num_heap_slots() > 0) {
1407 if (s->calls_sloppy_eval()) {
1438 Variable* var = proxy->var();
1443 Variable* local = var->local_if_not_shadowed();
1445 if (local->mode() ==
LET || local->mode() ==
CONST ||
1447 __ CompareRoot(
rax, Heap::kTheHoleValueRootIndex);
1450 __ LoadRoot(
rax, Heap::kUndefinedValueRootIndex);
1453 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1464 Variable* var = proxy->var();
1468 switch (var->location()) {
1470 Comment cmnt(
masm_,
"[ Global variable");
1473 if (FLAG_vector_ics) {
1485 Comment cmnt(
masm_, var->IsContextSlot() ?
"[ Context slot"
1487 if (var->binding_needs_init()) {
1511 bool skip_init_check;
1512 if (var->scope()->DeclarationScope() !=
scope()->DeclarationScope()) {
1513 skip_init_check =
false;
1519 var->initializer_position() < proxy->position();
1522 if (!skip_init_check) {
1526 __ CompareRoot(
rax, Heap::kTheHoleValueRootIndex);
1528 if (var->mode() ==
LET || var->mode() ==
CONST) {
1532 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1536 __ LoadRoot(
rax, Heap::kUndefinedValueRootIndex);
1548 Comment cmnt(
masm_,
"[ Lookup slot");
1556 __ CallRuntime(Runtime::kLoadLookupSlot, 2);
1565 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1566 Comment cmnt(
masm_,
"[ RegExpLiteral");
1575 int literal_offset =
1578 __ CompareRoot(
rbx, Heap::kUndefinedValueRootIndex);
1585 __ Push(expr->pattern());
1587 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1590 __ bind(&materialized);
1592 Label allocated, runtime_allocate;
1596 __ bind(&runtime_allocate);
1599 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1602 __ bind(&allocated);
1620 if (expression ==
NULL) {
1621 __ PushRoot(Heap::kNullValueRootIndex);
1628 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1629 Comment cmnt(
masm_,
"[ ObjectLiteral");
1631 expr->BuildConstantProperties(isolate());
1632 Handle<FixedArray> constant_properties = expr->constant_properties();
1633 int flags = expr->fast_elements()
1634 ? ObjectLiteral::kFastElements
1635 : ObjectLiteral::kNoFlags;
1636 flags |= expr->has_function()
1637 ? ObjectLiteral::kHasFunction
1638 : ObjectLiteral::kNoFlags;
1639 int properties_count = constant_properties->length() / 2;
1640 if (expr->may_store_doubles() || expr->depth() > 1 ||
1641 masm()->serializer_enabled() ||
flags != ObjectLiteral::kFastElements ||
1646 __ Push(constant_properties);
1648 __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
1653 __ Move(
rcx, constant_properties);
1655 FastCloneShallowObjectStub stub(isolate(), properties_count);
1661 bool result_saved =
false;
1666 expr->CalculateEmitStore(zone());
1668 AccessorTable accessor_table(zone());
1669 for (
int i = 0;
i < expr->properties()->length();
i++) {
1670 ObjectLiteral::Property*
property = expr->properties()->at(
i);
1671 if (property->IsCompileTimeValue())
continue;
1673 Literal* key =
property->key();
1674 Expression* value =
property->value();
1675 if (!result_saved) {
1677 result_saved =
true;
1679 switch (property->kind()) {
1682 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1685 case ObjectLiteral::Property::COMPUTED:
1686 if (key->value()->IsInternalizedString()) {
1687 if (property->emit_store()) {
1702 if (property->emit_store()) {
1704 __ CallRuntime(Runtime::kSetProperty, 4);
1709 case ObjectLiteral::Property::PROTOTYPE:
1712 if (property->emit_store()) {
1713 __ CallRuntime(Runtime::kSetPrototype, 2);
1718 case ObjectLiteral::Property::GETTER:
1719 accessor_table.lookup(key)->second->getter = value;
1721 case ObjectLiteral::Property::SETTER:
1722 accessor_table.lookup(key)->second->setter = value;
1729 for (AccessorTable::Iterator it = accessor_table.begin();
1730 it != accessor_table.end();
1737 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
1740 if (expr->has_function()) {
1743 __ CallRuntime(Runtime::kToFastProperties, 1);
1754 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1755 Comment cmnt(
masm_,
"[ ArrayLiteral");
1757 expr->BuildConstantElements(isolate());
1758 int flags = expr->depth() == 1
1759 ? ArrayLiteral::kShallowElements
1760 : ArrayLiteral::kNoFlags;
1762 ZoneList<Expression*>* subexprs = expr->values();
1763 int length = subexprs->length();
1764 Handle<FixedArray> constant_elements = expr->constant_elements();
1765 DCHECK_EQ(2, constant_elements->length());
1767 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1768 bool has_constant_fast_elements =
1770 Handle<FixedArrayBase> constant_elements_values(
1771 FixedArrayBase::cast(constant_elements->get(1)));
1774 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
1784 __ Push(constant_elements);
1786 __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
1791 __ Move(
rcx, constant_elements);
1792 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1796 bool result_saved =
false;
1800 for (
int i = 0;
i < length;
i++) {
1801 Expression* subexpr = subexprs->at(
i);
1806 if (!result_saved) {
1809 result_saved =
true;
1829 StoreArrayLiteralElementStub stub(isolate());
1845 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1846 DCHECK(expr->target()->IsValidReferenceExpression());
1848 Comment cmnt(
masm_,
"[ Assignment");
1856 NAMED_SUPER_PROPERTY
1859 Property*
property = expr->target()->AsProperty();
1860 if (property !=
NULL) {
1861 assign_type = (
property->key()->IsPropertyName())
1862 ? (property->IsSuperAccess() ? NAMED_SUPER_PROPERTY
1868 switch (assign_type) {
1873 if (expr->is_compound()) {
1881 case NAMED_SUPER_PROPERTY:
1885 if (expr->is_compound()) {
1891 if (expr->is_compound()) {
1906 if (expr->is_compound()) {
1907 { AccumulatorValueContext
context(
this);
1908 switch (assign_type) {
1917 case NAMED_SUPER_PROPERTY:
1936 AccumulatorValueContext
context(
this);
1956 switch (assign_type) {
1966 case NAMED_SUPER_PROPERTY:
1976 void FullCodeGenerator::VisitYield(Yield* expr) {
1977 Comment cmnt(
masm_,
"[ Yield");
1982 switch (expr->yield_kind()) {
1983 case Yield::kSuspend:
1988 case Yield::kInitial: {
1989 Label suspend, continuation, post_runtime, resume;
1993 __ bind(&continuation);
2009 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2012 __ bind(&post_runtime);
2022 case Yield::kFinal: {
2034 case Yield::kDelegating: {
2041 Label l_catch, l_try, l_suspend, l_continuation, l_resume;
2042 Label l_next, l_call, l_loop;
2047 __ LoadRoot(
rax, Heap::kUndefinedValueRootIndex);
2053 __ LoadRoot(load_name, Heap::kthrow_stringRootIndex);
2064 __ PushTryHandler(StackHandler::CATCH, expr->index());
2068 __ bind(&l_continuation);
2070 __ bind(&l_suspend);
2071 const int generator_object_depth =
kPointerSize + handler_size;
2072 __ movp(
rax, Operand(
rsp, generator_object_depth));
2081 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2092 __ LoadRoot(load_name, Heap::knext_stringRootIndex);
2100 if (FLAG_vector_ics) {
2104 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
2116 __ Move(load_receiver,
rax);
2118 __ LoadRoot(load_name, Heap::kdone_stringRootIndex);
2119 if (FLAG_vector_ics) {
2130 __ Pop(load_receiver);
2131 __ LoadRoot(load_name, Heap::kvalue_stringRootIndex);
2132 if (FLAG_vector_ics) {
2156 Label wrong_state, closed_state, done;
2162 __ j(
less, &wrong_state);
2173 __ LoadSharedFunctionInfoSpecialField(
rdx,
rdx,
2175 __ LoadRoot(
rcx, Heap::kTheHoleValueRootIndex);
2176 Label push_argument_holes, push_frame;
2177 __ bind(&push_argument_holes);
2178 __ subp(
rdx, Immediate(1));
2181 __ jmp(&push_argument_holes);
2186 __ bind(&push_frame);
2187 __ call(&resume_frame);
2189 __ bind(&resume_frame);
2204 __ cmpp(
rdx, Immediate(0));
2207 __ SmiToInteger64(
rcx,
2213 __ bind(&slow_resume);
2218 Label push_operand_holes, call_resume;
2219 __ bind(&push_operand_holes);
2220 __ subp(
rdx, Immediate(1));
2223 __ jmp(&push_operand_holes);
2224 __ bind(&call_resume);
2228 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
2230 __ Abort(kGeneratorFailedToResume);
2233 __ bind(&closed_state);
2236 __ PushRoot(Heap::kUndefinedValueRootIndex);
2242 __ CallRuntime(Runtime::kThrow, 1);
2247 __ bind(&wrong_state);
2249 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
2260 Handle<Map>
map(isolate()->native_context()->iterator_result_map());
2265 __ bind(&gc_required);
2267 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2271 __ bind(&allocated);
2274 __ Move(
rdx, isolate()->factory()->ToBoolean(done));
2278 isolate()->factory()->empty_fixed_array());
2280 isolate()->factory()->empty_fixed_array());
2295 Literal* key = prop->key()->AsLiteral();
2296 DCHECK(!prop->IsSuperAccess());
2299 if (FLAG_vector_ics) {
2312 Literal* key = prop->key()->AsLiteral();
2313 DCHECK(!key->value()->IsSmi());
2314 DCHECK(prop->IsSuperAccess());
2317 __ CallRuntime(Runtime::kLoadFromSuper, 3);
2323 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
2324 if (FLAG_vector_ics) {
2329 CallIC(ic, prop->PropertyFeedbackId());
2338 Expression* right) {
2342 Label done, stub_call, smi_case;
2346 JumpPatchSite patch_site(
masm_);
2347 patch_site.EmitJumpIfSmi(
rax, &smi_case, Label::kNear);
2349 __ bind(&stub_call);
2351 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op,
mode).code();
2352 CallIC(code, expr->BinaryOperationFeedbackId());
2353 patch_site.EmitPatchInfo();
2354 __ jmp(&done, Label::kNear);
2365 __ SmiShiftLogicalRight(
rax,
rdx,
rcx, &stub_call);
2379 case Token::BIT_AND:
2382 case Token::BIT_XOR:
2399 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op,
mode).code();
2400 JumpPatchSite patch_site(
masm_);
2401 CallIC(code, expr->BinaryOperationFeedbackId());
2402 patch_site.EmitPatchInfo();
2408 DCHECK(expr->IsValidReferenceExpression());
2414 Property* prop = expr->AsProperty();
2416 assign_type = (prop->key()->IsPropertyName())
2421 switch (assign_type) {
2423 Variable* var = expr->AsVariableProxy()->var();
2434 prop->key()->AsLiteral()->value());
2446 CodeFactory::KeyedStoreIC(isolate(),
strict_mode()).code();
2457 __ movp(location,
rax);
2458 if (var->IsContextSlot()) {
2460 __ RecordWriteContextSlot(
2468 if (var->IsUnallocated()) {
2474 }
else if (op == Token::INIT_CONST_LEGACY) {
2476 DCHECK(!var->IsParameter());
2477 if (var->IsLookupSlot()) {
2481 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3);
2483 DCHECK(var->IsStackLocal() || var->IsContextSlot());
2486 __ movp(
rdx, location);
2487 __ CompareRoot(
rdx, Heap::kTheHoleValueRootIndex);
2493 }
else if (var->mode() ==
LET && op != Token::INIT_LET) {
2495 DCHECK(!var->IsLookupSlot());
2496 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2499 __ movp(
rdx, location);
2500 __ CompareRoot(
rdx, Heap::kTheHoleValueRootIndex);
2503 __ CallRuntime(Runtime::kThrowReferenceError, 1);
2507 }
else if (!var->is_const_mode() || op == Token::INIT_CONST) {
2508 if (var->IsLookupSlot()) {
2514 __ CallRuntime(Runtime::kStoreLookupSlot, 4);
2518 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2522 __ movp(
rdx, location);
2523 __ CompareRoot(
rdx, Heap::kTheHoleValueRootIndex);
2524 __ Check(
equal, kLetBindingReInitialization);
2535 Property* prop = expr->target()->AsProperty();
2537 DCHECK(prop->key()->IsLiteral());
2554 Property* prop = expr->target()->AsProperty();
2556 Literal* key = prop->key()->AsLiteral();
2562 : Runtime::kStoreToSuper_Sloppy),
2576 Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(),
strict_mode()).code();
2577 CallIC(ic, expr->AssignmentFeedbackId());
2584 void FullCodeGenerator::VisitProperty(Property* expr) {
2585 Comment cmnt(
masm_,
"[ Property");
2586 Expression* key = expr->key();
2588 if (key->IsPropertyName()) {
2589 if (!expr->IsSuperAccess()) {
2614 TypeFeedbackId ast_id) {
2622 Expression* callee = expr->expression();
2624 CallICState::CallType call_type =
2625 callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD;
2627 if (call_type == CallICState::FUNCTION) {
2628 { StackValueContext
context(
this);
2634 __ Push(isolate()->factory()->undefined_value());
2637 DCHECK(callee->IsProperty());
2638 DCHECK(!callee->AsProperty()->IsSuperAccess());
2652 Expression* callee = expr->expression();
2653 DCHECK(callee->IsProperty());
2654 Property* prop = callee->AsProperty();
2655 DCHECK(prop->IsSuperAccess());
2658 Literal* key = prop->key()->AsLiteral();
2659 DCHECK(!key->value()->IsSmi());
2661 SuperReference* super_ref = prop->obj()->AsSuperReference();
2676 __ CallRuntime(Runtime::kLoadFromSuper, 3);
2684 EmitCall(expr, CallICState::METHOD);
2694 Expression* callee = expr->expression();
2697 DCHECK(callee->IsProperty());
2707 EmitCall(expr, CallICState::METHOD);
2713 ZoneList<Expression*>* args = expr->arguments();
2714 int arg_count = args->length();
2715 { PreservePositionScope
scope(
masm()->positions_recorder());
2716 for (
int i = 0;
i < arg_count;
i++) {
2724 isolate(), arg_count, call_type);
2742 if (arg_count > 0) {
2745 __ PushRoot(Heap::kUndefinedValueRootIndex);
2750 __ Push(args.GetReceiverOperand());
2759 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
2763 void FullCodeGenerator::VisitCall(Call* expr) {
2767 expr->return_is_recorded_ =
false;
2770 Comment cmnt(
masm_,
"[ Call");
2771 Expression* callee = expr->expression();
2772 Call::CallType call_type = expr->GetCallType(isolate());
2774 if (call_type == Call::POSSIBLY_EVAL_CALL) {
2778 ZoneList<Expression*>* args = expr->arguments();
2779 int arg_count = args->length();
2780 { PreservePositionScope pos_scope(
masm()->positions_recorder());
2782 __ PushRoot(Heap::kUndefinedValueRootIndex);
2785 for (
int i = 0;
i < arg_count;
i++) {
2808 }
else if (call_type == Call::GLOBAL_CALL) {
2811 }
else if (call_type == Call::LOOKUP_SLOT_CALL) {
2813 VariableProxy* proxy = callee->AsVariableProxy();
2816 { PreservePositionScope
scope(
masm()->positions_recorder());
2826 __ CallRuntime(Runtime::kLoadLookupSlot, 2);
2832 if (done.is_linked()) {
2834 __ jmp(&call, Label::kNear);
2840 __ PushRoot(Heap::kUndefinedValueRootIndex);
2847 }
else if (call_type == Call::PROPERTY_CALL) {
2848 Property*
property = callee->AsProperty();
2849 bool is_named_call =
property->key()->IsPropertyName();
2851 if (property->IsSuperAccess() && is_named_call) {
2855 PreservePositionScope
scope(
masm()->positions_recorder());
2858 if (is_named_call) {
2865 DCHECK(call_type == Call::OTHER_CALL);
2867 { PreservePositionScope
scope(
masm()->positions_recorder());
2870 __ PushRoot(Heap::kUndefinedValueRootIndex);
2877 DCHECK(expr->return_is_recorded_);
2882 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
2883 Comment cmnt(
masm_,
"[ CallNew");
2894 ZoneList<Expression*>* args = expr->arguments();
2895 int arg_count = args->length();
2896 for (
int i = 0;
i < arg_count;
i++) {
2905 __ Set(
rax, arg_count);
2909 if (FLAG_pretenuring_call_new) {
2911 DCHECK(expr->AllocationSiteFeedbackSlot() ==
2912 expr->CallNewFeedbackSlot() + 1);
2925 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2926 ZoneList<Expression*>* args = expr->arguments();
2927 DCHECK(args->length() == 1);
2931 Label materialize_true, materialize_false;
2932 Label* if_true =
NULL;
2933 Label* if_false =
NULL;
2934 Label* fall_through =
NULL;
2935 context()->PrepareTest(&materialize_true, &materialize_false,
2936 &if_true, &if_false, &fall_through);
2939 __ JumpIfSmi(
rax, if_true);
2942 context()->Plug(if_true, if_false);
2946 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
2947 ZoneList<Expression*>* args = expr->arguments();
2948 DCHECK(args->length() == 1);
2952 Label materialize_true, materialize_false;
2953 Label* if_true =
NULL;
2954 Label* if_false =
NULL;
2955 Label* fall_through =
NULL;
2956 context()->PrepareTest(&materialize_true, &materialize_false,
2957 &if_true, &if_false, &fall_through);
2961 Split(non_negative_smi, if_true, if_false, fall_through);
2963 context()->Plug(if_true, if_false);
2967 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
2968 ZoneList<Expression*>* args = expr->arguments();
2969 DCHECK(args->length() == 1);
2973 Label materialize_true, materialize_false;
2974 Label* if_true =
NULL;
2975 Label* if_false =
NULL;
2976 Label* fall_through =
NULL;
2977 context()->PrepareTest(&materialize_true, &materialize_false,
2978 &if_true, &if_false, &fall_through);
2980 __ JumpIfSmi(
rax, if_false);
2981 __ CompareRoot(
rax, Heap::kNullValueRootIndex);
2995 context()->Plug(if_true, if_false);
2999 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
3000 ZoneList<Expression*>* args = expr->arguments();
3001 DCHECK(args->length() == 1);
3005 Label materialize_true, materialize_false;
3006 Label* if_true =
NULL;
3007 Label* if_false =
NULL;
3008 Label* fall_through =
NULL;
3009 context()->PrepareTest(&materialize_true, &materialize_false,
3010 &if_true, &if_false, &fall_through);
3012 __ JumpIfSmi(
rax, if_false);
3017 context()->Plug(if_true, if_false);
3021 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
3022 ZoneList<Expression*>* args = expr->arguments();
3023 DCHECK(args->length() == 1);
3027 Label materialize_true, materialize_false;
3028 Label* if_true =
NULL;
3029 Label* if_false =
NULL;
3030 Label* fall_through =
NULL;
3031 context()->PrepareTest(&materialize_true, &materialize_false,
3032 &if_true, &if_false, &fall_through);
3034 __ JumpIfSmi(
rax, if_false);
3041 context()->Plug(if_true, if_false);
3045 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
3046 CallRuntime* expr) {
3047 ZoneList<Expression*>* args = expr->arguments();
3048 DCHECK(args->length() == 1);
3052 Label materialize_true, materialize_false, skip_lookup;
3053 Label* if_true =
NULL;
3054 Label* if_false =
NULL;
3055 Label* fall_through =
NULL;
3056 context()->PrepareTest(&materialize_true, &materialize_false,
3057 &if_true, &if_false, &fall_through);
3059 __ AssertNotSmi(
rax);
3071 __ CompareRoot(
rcx, Heap::kHashTableMapRootIndex);
3077 Label entry, loop, done;
3080 __ NumberOfOwnDescriptors(
rcx,
rbx);
3081 __ cmpp(
rcx, Immediate(0));
3084 __ LoadInstanceDescriptors(
rbx,
r8);
3098 __ Cmp(
rdx, isolate()->factory()->value_of_string());
3111 __ bind(&skip_lookup);
3124 Split(
equal, if_true, if_false, fall_through);
3126 context()->Plug(if_true, if_false);
3130 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
3131 ZoneList<Expression*>* args = expr->arguments();
3132 DCHECK(args->length() == 1);
3136 Label materialize_true, materialize_false;
3137 Label* if_true =
NULL;
3138 Label* if_false =
NULL;
3139 Label* fall_through =
NULL;
3140 context()->PrepareTest(&materialize_true, &materialize_false,
3141 &if_true, &if_false, &fall_through);
3143 __ JumpIfSmi(
rax, if_false);
3146 Split(
equal, if_true, if_false, fall_through);
3148 context()->Plug(if_true, if_false);
3152 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
3153 ZoneList<Expression*>* args = expr->arguments();
3154 DCHECK(args->length() == 1);
3158 Label materialize_true, materialize_false;
3159 Label* if_true =
NULL;
3160 Label* if_false =
NULL;
3161 Label* fall_through =
NULL;
3162 context()->PrepareTest(&materialize_true, &materialize_false,
3163 &if_true, &if_false, &fall_through);
3171 Immediate(0x00000000));
3173 Split(
equal, if_true, if_false, fall_through);
3175 context()->Plug(if_true, if_false);
3179 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
3180 ZoneList<Expression*>* args = expr->arguments();
3181 DCHECK(args->length() == 1);
3185 Label materialize_true, materialize_false;
3186 Label* if_true =
NULL;
3187 Label* if_false =
NULL;
3188 Label* fall_through =
NULL;
3189 context()->PrepareTest(&materialize_true, &materialize_false,
3190 &if_true, &if_false, &fall_through);
3192 __ JumpIfSmi(
rax, if_false);
3195 Split(
equal, if_true, if_false, fall_through);
3197 context()->Plug(if_true, if_false);
3201 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
3202 ZoneList<Expression*>* args = expr->arguments();
3203 DCHECK(args->length() == 1);
3207 Label materialize_true, materialize_false;
3208 Label* if_true =
NULL;
3209 Label* if_false =
NULL;
3210 Label* fall_through =
NULL;
3211 context()->PrepareTest(&materialize_true, &materialize_false,
3212 &if_true, &if_false, &fall_through);
3214 __ JumpIfSmi(
rax, if_false);
3217 Split(
equal, if_true, if_false, fall_through);
3219 context()->Plug(if_true, if_false);
3224 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
3225 DCHECK(expr->arguments()->length() == 0);
3227 Label materialize_true, materialize_false;
3228 Label* if_true =
NULL;
3229 Label* if_false =
NULL;
3230 Label* fall_through =
NULL;
3231 context()->PrepareTest(&materialize_true, &materialize_false,
3232 &if_true, &if_false, &fall_through);
3238 Label check_frame_marker;
3245 __ bind(&check_frame_marker);
3249 Split(
equal, if_true, if_false, fall_through);
3251 context()->Plug(if_true, if_false);
3255 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
3256 ZoneList<Expression*>* args = expr->arguments();
3257 DCHECK(args->length() == 2);
3263 Label materialize_true, materialize_false;
3264 Label* if_true =
NULL;
3265 Label* if_false =
NULL;
3266 Label* fall_through =
NULL;
3267 context()->PrepareTest(&materialize_true, &materialize_false,
3268 &if_true, &if_false, &fall_through);
3273 Split(
equal, if_true, if_false, fall_through);
3275 context()->Plug(if_true, if_false);
3279 void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
3280 ZoneList<Expression*>* args = expr->arguments();
3281 DCHECK(args->length() == 1);
3294 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
3295 DCHECK(expr->arguments()->length() == 0);
3317 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
3318 ZoneList<Expression*>* args = expr->arguments();
3319 DCHECK(args->length() == 1);
3320 Label done,
null,
function, non_function_constructor;
3325 __ JumpIfSmi(
rax, &
null);
3359 __ Move(
rax, isolate()->factory()->Function_string());
3363 __ bind(&non_function_constructor);
3364 __ Move(
rax, isolate()->factory()->Object_string());
3369 __ LoadRoot(
rax, Heap::kNullValueRootIndex);
3378 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
3380 SubStringStub stub(isolate());
3381 ZoneList<Expression*>* args = expr->arguments();
3382 DCHECK(args->length() == 3);
3391 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
3393 RegExpExecStub stub(isolate());
3394 ZoneList<Expression*>* args = expr->arguments();
3395 DCHECK(args->length() == 4);
3405 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
3406 ZoneList<Expression*>* args = expr->arguments();
3407 DCHECK(args->length() == 1);
3413 __ JumpIfSmi(
rax, &done);
3424 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
3425 ZoneList<Expression*>* args = expr->arguments();
3426 DCHECK(args->length() == 2);
3428 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value()));
3432 Label runtime, done, not_date_object;
3433 Register
object =
rax;
3434 Register result =
rax;
3435 Register scratch =
rcx;
3437 __ JumpIfSmi(
object, ¬_date_object);
3441 if (index->value() == 0) {
3446 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
3447 Operand stamp_operand =
__ ExternalOperand(stamp);
3448 __ movp(scratch, stamp_operand);
3456 __ PrepareCallCFunction(2);
3459 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3464 __ bind(¬_date_object);
3465 __ CallRuntime(Runtime::kThrowNotDateError, 0);
3471 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
3472 ZoneList<Expression*>* args = expr->arguments();
3475 Register
string =
rax;
3476 Register index =
rbx;
3477 Register value =
rcx;
3485 if (FLAG_debug_code) {
3486 __ Check(
__ CheckSmi(value), kNonSmiValue);
3487 __ Check(
__ CheckSmi(index), kNonSmiValue);
3490 __ SmiToInteger32(value, value);
3491 __ SmiToInteger32(index, index);
3493 if (FLAG_debug_code) {
3495 __ EmitSeqStringSetCharCheck(
string, index, value, one_byte_seq_type);
3504 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
3505 ZoneList<Expression*>* args = expr->arguments();
3508 Register
string =
rax;
3509 Register index =
rbx;
3510 Register value =
rcx;
3518 if (FLAG_debug_code) {
3519 __ Check(
__ CheckSmi(value), kNonSmiValue);
3520 __ Check(
__ CheckSmi(index), kNonSmiValue);
3523 __ SmiToInteger32(value, value);
3524 __ SmiToInteger32(index, index);
3526 if (FLAG_debug_code) {
3528 __ EmitSeqStringSetCharCheck(
string, index, value, two_byte_seq_type);
3537 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
3539 ZoneList<Expression*>* args = expr->arguments();
3540 DCHECK(args->length() == 2);
3549 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
3550 ZoneList<Expression*>* args = expr->arguments();
3551 DCHECK(args->length() == 2);
3559 __ JumpIfSmi(
rbx, &done);
3577 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
3578 ZoneList<Expression*>* args = expr->arguments();
3584 NumberToStringStub stub(isolate());
3590 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
3591 ZoneList<Expression*>* args = expr->arguments();
3592 DCHECK(args->length() == 1);
3597 StringCharFromCodeGenerator generator(
rax,
rbx);
3598 generator.GenerateFast(
masm_);
3601 NopRuntimeCallHelper call_helper;
3602 generator.GenerateSlow(
masm_, call_helper);
3609 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
3610 ZoneList<Expression*>* args = expr->arguments();
3611 DCHECK(args->length() == 2);
3616 Register
object =
rbx;
3617 Register index =
rax;
3618 Register result =
rdx;
3622 Label need_conversion;
3623 Label index_out_of_range;
3625 StringCharCodeAtGenerator generator(
object,
3630 &index_out_of_range,
3632 generator.GenerateFast(
masm_);
3635 __ bind(&index_out_of_range);
3638 __ LoadRoot(result, Heap::kNanValueRootIndex);
3641 __ bind(&need_conversion);
3644 __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
3647 NopRuntimeCallHelper call_helper;
3648 generator.GenerateSlow(
masm_, call_helper);
3655 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
3656 ZoneList<Expression*>* args = expr->arguments();
3657 DCHECK(args->length() == 2);
3662 Register
object =
rbx;
3663 Register index =
rax;
3664 Register scratch =
rdx;
3665 Register result =
rax;
3669 Label need_conversion;
3670 Label index_out_of_range;
3672 StringCharAtGenerator generator(
object,
3678 &index_out_of_range,
3680 generator.GenerateFast(
masm_);
3683 __ bind(&index_out_of_range);
3686 __ LoadRoot(result, Heap::kempty_stringRootIndex);
3689 __ bind(&need_conversion);
3695 NopRuntimeCallHelper call_helper;
3696 generator.GenerateSlow(
masm_, call_helper);
3703 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3704 ZoneList<Expression*>* args = expr->arguments();
3716 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3717 ZoneList<Expression*>* args = expr->arguments();
3723 StringCompareStub stub(isolate());
3729 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
3730 ZoneList<Expression*>* args = expr->arguments();
3731 DCHECK(args->length() >= 2);
3733 int arg_count = args->length() - 2;
3734 for (
int i = 0;
i < arg_count + 1;
i++) {
3739 Label runtime, done;
3741 __ JumpIfSmi(
rax, &runtime);
3747 ParameterCount count(arg_count);
3754 __ CallRuntime(Runtime::kCall, args->length());
3761 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3762 RegExpConstructResultStub stub(isolate());
3763 ZoneList<Expression*>* args = expr->arguments();
3764 DCHECK(args->length() == 3);
3775 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3776 ZoneList<Expression*>* args = expr->arguments();
3780 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value();
3782 Handle<FixedArray> jsfunction_result_caches(
3783 isolate()->native_context()->jsfunction_result_caches());
3784 if (jsfunction_result_caches->length() <= cache_id) {
3785 __ Abort(kAttemptToUseUndefinedCache);
3786 __ LoadRoot(
rax, Heap::kUndefinedValueRootIndex);
3794 Register cache =
rbx;
3804 Label done, not_found;
3819 __ jmp(&done, Label::kNear);
3821 __ bind(¬_found);
3825 __ CallRuntime(Runtime::kGetFromCache, 2);
3832 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3833 ZoneList<Expression*>* args = expr->arguments();
3834 DCHECK(args->length() == 1);
3838 Label materialize_true, materialize_false;
3839 Label* if_true =
NULL;
3840 Label* if_false =
NULL;
3841 Label* fall_through =
NULL;
3842 context()->PrepareTest(&materialize_true, &materialize_false,
3843 &if_true, &if_false, &fall_through);
3851 context()->Plug(if_true, if_false);
3855 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3856 ZoneList<Expression*>* args = expr->arguments();
3857 DCHECK(args->length() == 1);
3860 __ AssertString(
rax);
3870 void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) {
3871 Label bailout, return_result, done, one_char_separator, long_separator,
3872 non_trivial_array, not_size_one_array, loop,
3873 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
3874 ZoneList<Expression*>* args = expr->arguments();
3875 DCHECK(args->length() == 2);
3881 Register array =
rax;
3882 Register elements =
no_reg;
3884 Register index =
rdx;
3886 Register string_length =
rcx;
3888 Register
string =
rsi;
3890 Register scratch =
rbx;
3892 Register array_length =
rdi;
3893 Register result_pos =
no_reg;
3904 __ JumpIfSmi(array, &bailout);
3909 __ CheckFastElements(scratch, &bailout);
3916 __ LoadRoot(
rax, Heap::kempty_stringRootIndex);
3917 __ jmp(&return_result);
3920 __ bind(&non_trivial_array);
3921 __ SmiToInteger32(array_length, array_length);
3922 __ movl(array_length_operand, array_length);
3934 __ Set(string_length, 0);
3939 __ cmpp(index, array_length);
3940 __ Assert(
below, kNoEmptyArraysHereInEmitFastOneByteArrayJoin);
3947 __ JumpIfSmi(
string, &bailout);
3950 __ andb(scratch, Immediate(
3954 __ AddSmiField(string_length,
3958 __ cmpl(index, array_length);
3968 __ cmpl(array_length, Immediate(1));
3971 __ jmp(&return_result);
3973 __ bind(¬_size_one_array);
3976 result_pos = array_length;
3985 __ movp(
string, separator_operand);
3986 __ JumpIfSmi(
string, &bailout);
3989 __ andb(scratch, Immediate(
4001 __ SmiToInteger32(scratch,
4004 __ imull(scratch, index);
4006 __ addl(string_length, scratch);
4012 __ AllocateOneByteString(result_pos, string_length, scratch, index,
string,
4014 __ movp(result_operand, result_pos);
4017 __ movp(
string, separator_operand);
4020 __ j(
equal, &one_char_separator);
4026 __ movl(scratch, array_length_operand);
4027 __ jmp(&loop_1_condition);
4041 __ SmiToInteger32(string_length,
4047 __ bind(&loop_1_condition);
4048 __ cmpl(index, scratch);
4054 __ LoadRoot(
rax, Heap::kUndefinedValueRootIndex);
4055 __ jmp(&return_result);
4059 __ bind(&one_char_separator);
4066 __ jmp(&loop_2_entry);
4077 __ movb(Operand(result_pos, 0), scratch);
4078 __ incp(result_pos);
4080 __ bind(&loop_2_entry);
4085 __ SmiToInteger32(string_length,
4091 __ cmpl(index, array_length_operand);
4097 __ bind(&long_separator);
4102 __ movl(index, array_length_operand);
4109 __ movp(
string, separator_operand);
4110 __ SmiToInteger32(scratch,
4114 __ movp(separator_operand,
string);
4118 __ jmp(&loop_3_entry);
4129 __ movp(
string, separator_operand);
4130 __ movl(string_length, scratch);
4131 __ CopyBytes(result_pos,
string, string_length, 2);
4133 __ bind(&loop_3_entry);
4136 __ SmiToInteger32(string_length,
4145 __ movp(
rax, result_operand);
4147 __ bind(&return_result);
4155 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
4156 DCHECK(expr->arguments()->length() == 0);
4157 ExternalReference debug_is_active =
4158 ExternalReference::debug_is_active_address(isolate());
4166 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4167 if (expr->function() !=
NULL &&
4169 Comment cmnt(
masm_,
"[ InlineRuntimeCall");
4174 Comment cmnt(
masm_,
"[ CallRuntime");
4175 ZoneList<Expression*>* args = expr->arguments();
4176 int arg_count = args->length();
4178 if (expr->is_jsruntime()) {
4186 if (FLAG_vector_ics) {
4199 for (
int i = 0;
i < arg_count;
i++) {
4215 for (
int i = 0;
i < arg_count;
i++) {
4220 __ CallRuntime(expr->function(), arg_count);
4226 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4227 switch (expr->op()) {
4228 case Token::DELETE: {
4229 Comment cmnt(
masm_,
"[ UnaryOperation (DELETE)");
4230 Property*
property = expr->expression()->AsProperty();
4231 VariableProxy* proxy = expr->expression()->AsVariableProxy();
4233 if (property !=
NULL) {
4239 }
else if (proxy !=
NULL) {
4240 Variable* var = proxy->var();
4244 if (var->IsUnallocated()) {
4250 }
else if (var->IsStackAllocated() || var->IsContextSlot()) {
4254 context()->Plug(var->is_this());
4260 __ CallRuntime(Runtime::kDeleteLookupSlot, 2);
4273 Comment cmnt(
masm_,
"[ UnaryOperation (VOID)");
4275 context()->Plug(Heap::kUndefinedValueRootIndex);
4280 Comment cmnt(
masm_,
"[ UnaryOperation (NOT)");
4285 }
else if (
context()->IsTest()) {
4289 test->false_label(),
4291 test->fall_through());
4292 context()->Plug(test->true_label(), test->false_label());
4299 Label materialize_true, materialize_false, done;
4304 __ bind(&materialize_true);
4306 if (
context()->IsAccumulatorValue()) {
4307 __ LoadRoot(
rax, Heap::kTrueValueRootIndex);
4309 __ PushRoot(Heap::kTrueValueRootIndex);
4311 __ jmp(&done, Label::kNear);
4312 __ bind(&materialize_false);
4314 if (
context()->IsAccumulatorValue()) {
4315 __ LoadRoot(
rax, Heap::kFalseValueRootIndex);
4317 __ PushRoot(Heap::kFalseValueRootIndex);
4324 case Token::TYPEOF: {
4325 Comment cmnt(
masm_,
"[ UnaryOperation (TYPEOF)");
4326 { StackValueContext
context(
this);
4329 __ CallRuntime(Runtime::kTypeof, 1);
4340 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
4341 DCHECK(expr->expression()->IsValidReferenceExpression());
4343 Comment cmnt(
masm_,
"[ CountOperation");
4350 Property* prop = expr->expression()->AsProperty();
4356 if (prop->IsSuperAccess()) {
4358 VisitSuperReference(prop->obj()->AsSuperReference());
4365 DCHECK(expr->expression()->AsVariableProxy()->var() !=
NULL);
4366 AccumulatorValueContext
context(
this);
4370 if (expr->is_postfix() && !
context()->IsEffect()) {
4397 Label done, stub_call;
4398 JumpPatchSite patch_site(
masm_);
4401 patch_site.EmitJumpIfNotSmi(
rax, &slow, Label::kNear);
4404 if (expr->is_postfix()) {
4409 switch (assign_type) {
4423 SmiOperationExecutionMode
mode;
4426 if (expr->op() == Token::INC) {
4431 __ jmp(&stub_call, Label::kNear);
4435 ToNumberStub convert_stub(isolate());
4436 __ CallStub(&convert_stub);
4439 if (expr->is_postfix()) {
4444 switch (assign_type) {
4462 __ bind(&stub_call);
4465 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), expr->binary_op(),
4467 CallIC(code, expr->CountBinOpFeedbackId());
4468 patch_site.EmitPatchInfo();
4472 switch (assign_type) {
4474 if (expr->is_postfix()) {
4476 { EffectContext
context(
this);
4497 prop->key()->AsLiteral()->value());
4501 if (expr->is_postfix()) {
4514 CodeFactory::KeyedStoreIC(isolate(),
strict_mode()).code();
4515 CallIC(ic, expr->CountStoreFeedbackId());
4517 if (expr->is_postfix()) {
4531 VariableProxy* proxy = expr->AsVariableProxy();
4535 if (proxy !=
NULL && proxy->var()->IsUnallocated()) {
4536 Comment cmnt(
masm_,
"[ Global variable");
4539 if (FLAG_vector_ics) {
4548 }
else if (proxy !=
NULL && proxy->var()->IsLookupSlot()) {
4549 Comment cmnt(
masm_,
"[ Lookup slot");
4559 __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
4572 Expression* sub_expr,
4573 Handle<String> check) {
4574 Label materialize_true, materialize_false;
4575 Label* if_true =
NULL;
4576 Label* if_false =
NULL;
4577 Label* fall_through =
NULL;
4578 context()->PrepareTest(&materialize_true, &materialize_false,
4579 &if_true, &if_false, &fall_through);
4581 { AccumulatorValueContext
context(
this);
4586 Factory* factory = isolate()->factory();
4588 __ JumpIfSmi(
rax, if_true);
4590 __ CompareRoot(
rax, Heap::kHeapNumberMapRootIndex);
4591 Split(
equal, if_true, if_false, fall_through);
4593 __ JumpIfSmi(
rax, if_false);
4599 Split(
zero, if_true, if_false, fall_through);
4601 __ JumpIfSmi(
rax, if_false);
4603 Split(
equal, if_true, if_false, fall_through);
4605 __ CompareRoot(
rax, Heap::kTrueValueRootIndex);
4607 __ CompareRoot(
rax, Heap::kFalseValueRootIndex);
4608 Split(
equal, if_true, if_false, fall_through);
4610 __ CompareRoot(
rax, Heap::kUndefinedValueRootIndex);
4612 __ JumpIfSmi(
rax, if_false);
4619 __ JumpIfSmi(
rax, if_false);
4624 Split(
equal, if_true, if_false, fall_through);
4626 __ JumpIfSmi(
rax, if_false);
4627 __ CompareRoot(
rax, Heap::kNullValueRootIndex);
4636 Split(
zero, if_true, if_false, fall_through);
4638 if (if_false != fall_through)
__ jmp(if_false);
4640 context()->Plug(if_true, if_false);
4644 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4645 Comment cmnt(
masm_,
"[ CompareOperation");
4654 Label materialize_true, materialize_false;
4655 Label* if_true =
NULL;
4656 Label* if_false =
NULL;
4657 Label* fall_through =
NULL;
4658 context()->PrepareTest(&materialize_true, &materialize_false,
4659 &if_true, &if_false, &fall_through);
4668 __ CompareRoot(
rax, Heap::kTrueValueRootIndex);
4669 Split(
equal, if_true, if_false, fall_through);
4672 case Token::INSTANCEOF: {
4679 Split(
zero, if_true, if_false, fall_through);
4689 JumpPatchSite patch_site(
masm_);
4690 if (inline_smi_code) {
4694 patch_site.EmitJumpIfNotSmi(
rcx, &slow_case, Label::kNear);
4697 __ bind(&slow_case);
4702 Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
4703 CallIC(ic, expr->CompareOperationFeedbackId());
4704 patch_site.EmitPatchInfo();
4708 Split(
cc, if_true, if_false, fall_through);
4714 context()->Plug(if_true, if_false);
4719 Expression* sub_expr,
4721 Label materialize_true, materialize_false;
4722 Label* if_true =
NULL;
4723 Label* if_false =
NULL;
4724 Label* fall_through =
NULL;
4725 context()->PrepareTest(&materialize_true, &materialize_false,
4726 &if_true, &if_false, &fall_through);
4730 if (expr->op() == Token::EQ_STRICT) {
4732 Heap::kNullValueRootIndex :
4733 Heap::kUndefinedValueRootIndex;
4734 __ CompareRoot(
rax, nil_value);
4735 Split(
equal, if_true, if_false, fall_through);
4738 CallIC(ic, expr->CompareOperationFeedbackId());
4742 context()->Plug(if_true, if_false);
4746 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4764 __ movp(Operand(
rbp, frame_offset), value);
4775 if (declaration_scope->is_global_scope() ||
4776 declaration_scope->is_module_scope()) {
4782 }
else if (declaration_scope->is_eval_scope()) {
4788 DCHECK(declaration_scope->is_function_scope());
4802 __ PopReturnAddressTo(
rdx);
4812 ExternalReference pending_message_obj =
4813 ExternalReference::address_of_pending_message_obj(isolate());
4814 __ Load(
rdx, pending_message_obj);
4817 ExternalReference has_pending_message =
4818 ExternalReference::address_of_has_pending_message(isolate());
4819 __ Load(
rdx, has_pending_message);
4823 ExternalReference pending_message_script =
4824 ExternalReference::address_of_pending_message_script(isolate());
4825 __ Load(
rdx, pending_message_script);
4835 ExternalReference pending_message_script =
4836 ExternalReference::address_of_pending_message_script(isolate());
4837 __ Store(pending_message_script,
rdx);
4841 ExternalReference has_pending_message =
4842 ExternalReference::address_of_has_pending_message(isolate());
4843 __ Store(has_pending_message,
rdx);
4846 ExternalReference pending_message_obj =
4847 ExternalReference::address_of_pending_message_obj(isolate());
4848 __ Store(pending_message_obj,
rdx);
4864 #define __ ACCESS_MASM(masm())
4868 int* context_length) {
4875 __ Drop(*stack_depth);
4876 if (*context_length > 0) {
4882 __ call(finally_entry_);
4885 *context_length = 0;
4893 static const byte kJnsInstruction = 0x79;
4894 static const byte kNopByteOne = 0x66;
4895 static const byte kNopByteTwo = 0x90;
4897 static const byte kCallInstruction = 0xe8;
4903 BackEdgeState target_state,
4904 Code* replacement_code) {
4906 Address jns_instr_address = call_target_address - 3;
4907 Address jns_offset_address = call_target_address - 2;
4909 switch (target_state) {
4915 *jns_instr_address = kJnsInstruction;
4916 *jns_offset_address = kJnsOffset;
4918 case ON_STACK_REPLACEMENT:
4919 case OSR_AFTER_STACK_CHECK:
4925 *jns_instr_address = kNopByteOne;
4926 *jns_offset_address = kNopByteTwo;
4932 replacement_code->entry());
4933 unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
4934 unoptimized_code, call_target_address, replacement_code);
4940 Code* unoptimized_code,
4943 Address jns_instr_address = call_target_address - 3;
4944 DCHECK_EQ(kCallInstruction, *(call_target_address - 1));
4946 if (*jns_instr_address == kJnsInstruction) {
4947 DCHECK_EQ(kJnsOffset, *(call_target_address - 2));
4948 DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(),
4954 DCHECK_EQ(kNopByteOne, *jns_instr_address);
4955 DCHECK_EQ(kNopByteTwo, *(call_target_address - 2));
4958 unoptimized_code) ==
4959 isolate->builtins()->OnStackReplacement()->entry()) {
4960 return ON_STACK_REPLACEMENT;
4963 DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4966 return OSR_AFTER_STACK_CHECK;
static const int kLengthOffset
Isolate * isolate() const
static Address target_address_at(Address pc, ConstantPoolArray *constant_pool)
static RelocInfo::Mode RelocInfoNone()
static void set_target_address_at(Address pc, ConstantPoolArray *constant_pool, Address target, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
static const int kJSReturnSequenceLength
int SizeOfCodeGeneratedSince(Label *label)
static void PatchAt(Code *unoptimized_code, Address pc, BackEdgeState target_state, Code *replacement_code)
static BackEdgeState GetBackEdgeState(Isolate *isolate, Code *unoptimized_code, Address pc_after)
static BailoutId Declarations()
static BailoutId FunctionEntry()
static Handle< Code > initialize_stub(Isolate *isolate, int argc, CallICState::CallType call_type)
static const int kValueOffset
static bool RecordPositions(MacroAssembler *masm, int pos, bool right_here=false)
static Condition ComputeCondition(Token::Value op)
static Handle< Code > GetUninitialized(Isolate *isolate, NilValue nil)
bool IsOptimizable() const
bool ShouldSelfOptimize()
void AddNoFrameRange(int from, int to)
static bool IsCompileTimeValue(Expression *expression)
static Handle< SharedFunctionInfo > BuildFunctionInfo(FunctionLiteral *node, Handle< Script > script, CompilationInfo *outer)
@ STRING_FUNCTION_PROTOTYPE_MAP_INDEX
@ JSFUNCTION_RESULT_CACHES_INDEX
static int SlotOffset(int index)
static const int kDescriptorSize
static const int kEnumCacheBridgeCacheOffset
static const int kEnumCacheOffset
static const int kFirstOffset
static const int kMaximumClonedProperties
static const int kLengthOffset
static const int kHeaderSize
static int OffsetOfElementAt(int index)
virtual void DropAndPlug(int count, Register reg) const
virtual void Plug(bool flag) const
virtual void DropAndPlug(int count, Register reg) const
virtual void Plug(bool flag) const
virtual void DropAndPlug(int count, Register reg) const
virtual void Plug(bool flag) const
virtual void DropAndPlug(int count, Register reg) const
static const TestContext * cast(const ExpressionContext *context)
virtual void Plug(bool flag) const
virtual NestedStatement * Exit(int *stack_depth, int *context_length)
static const int kMaxBackEdgeWeight
void EmitAccessor(Expression *expression)
void Split(Condition cc, Label *if_true, Label *if_false, Label *fall_through)
void EmitBinaryOp(BinaryOperation *expr, Token::Value op, OverwriteMode mode)
void EmitLiteralCompareTypeof(Expression *expr, Expression *sub_expr, Handle< String > check)
void VisitDeclarations(ZoneList< Declaration * > *declarations)
void PrepareForBailoutForId(BailoutId id, State state)
void EmitNewClosure(Handle< SharedFunctionInfo > info, bool pretenure)
void GetVar(Register destination, Variable *var)
static Register context_register()
ZoneList< Handle< Object > > * globals_
void VisitForControl(Expression *expr, Label *if_true, Label *if_false, Label *fall_through)
void PushFunctionArgumentForContextAllocation()
void CallLoadIC(ContextualMode mode, TypeFeedbackId id=TypeFeedbackId::None())
bool generate_debug_code_
void RecordBackEdge(BailoutId osr_ast_id)
MemOperand StackOperand(Variable *var)
void EmitVariableLoad(VariableProxy *proxy)
friend class NestedStatement
void EmitReturnSequence()
void SetVar(Variable *var, Register source, Register scratch0, Register scratch1)
MemOperand ContextSlotOperandCheckExtensions(Variable *var, Label *slow)
void EmitKeyedPropertyAssignment(Assignment *expr)
void DeclareGlobals(Handle< FixedArray > pairs)
void EmitResolvePossiblyDirectEval(int arg_count)
void VisitForStackValue(Expression *expr)
void EmitKeyedCallWithLoadIC(Call *expr, Expression *key)
void EmitProfilingCounterReset()
void EmitKeyedPropertyLoad(Property *expr)
void EmitDebugCheckDeclarationContext(Variable *variable)
void EmitUnwindBeforeReturn()
FunctionLiteral * function()
void EmitNamedSuperPropertyLoad(Property *expr)
Handle< Cell > profiling_counter_
bool TryLiteralCompare(CompareOperation *compare)
void increment_loop_depth()
void SetStatementPosition(Statement *stmt)
Handle< FixedArray > FeedbackVector()
void StoreToFrameField(int frame_offset, Register value)
void LoadContextField(Register dst, int context_index)
const ExpressionContext * context()
void EmitNamedPropertyLoad(Property *expr)
void EmitBackEdgeBookkeeping(IterationStatement *stmt, Label *back_edge_target)
void DoTest(Expression *condition, Label *if_true, Label *if_false, Label *fall_through)
void VisitForAccumulatorValue(Expression *expr)
void PrepareForBailout(Expression *node, State state)
void CallStoreIC(TypeFeedbackId id=TypeFeedbackId::None())
MemOperand VarOperand(Variable *var, Register scratch)
void DeclareModules(Handle< FixedArray > descriptions)
void EmitGeneratorResume(Expression *generator, Expression *value, JSGeneratorObject::ResumeMode resume_mode)
void VisitForEffect(Expression *expr)
void EmitAssignment(Expression *expr)
void EmitCall(Call *expr, CallICState::CallType=CallICState::FUNCTION)
void SetFunctionPosition(FunctionLiteral *fun)
int DeclareGlobalsFlags()
void EmitLoadHomeObject(SuperReference *expr)
void EmitStoreToStackLocalOrContextSlot(Variable *var, MemOperand location)
void decrement_loop_depth()
void EmitInlineSmiBinaryOp(BinaryOperation *expr, Token::Value op, OverwriteMode mode, Expression *left, Expression *right)
void EmitLiteralCompareNil(CompareOperation *expr, Expression *sub_expr, NilValue nil)
void EmitVariableAssignment(Variable *var, Token::Value op)
void CallIC(Handle< Code > code, TypeFeedbackId id=TypeFeedbackId::None())
void EmitCreateIteratorResult(bool done)
void EmitLoadGlobalCheckExtensions(VariableProxy *proxy, TypeofState typeof_state, Label *slow)
void EmitCallWithLoadIC(Call *expr)
void EnsureSlotContainsAllocationSite(int slot)
void PrepareForBailoutBeforeSplit(Expression *expr, bool should_normalize, Label *if_true, Label *if_false)
Handle< Script > script()
void EmitInlineRuntimeCall(CallRuntime *expr)
void SetSourcePosition(int pos)
void EmitSuperCallWithLoadIC(Call *expr)
void EmitNamedSuperPropertyAssignment(Assignment *expr)
void EmitNamedPropertyAssignment(Assignment *expr)
Handle< FixedArray > handler_table_
void RecordJSReturnSite(Call *call)
static Register result_register()
void VisitForTypeofValue(Expression *expr)
void EmitDynamicLookupFastCase(VariableProxy *proxy, TypeofState typeof_state, Label *slow, Label *done)
bool ShouldInlineSmiCase(Token::Value op)
Handle< FixedArray > handler_table()
void EmitProfilingCounterDecrement(int delta)
void VisitInDuplicateContext(Expression *expr)
static const int kBuiltinsOffset
static const int kNativeContextOffset
static const int kGlobalProxyOffset
static const int kMapOffset
static const int kLengthOffset
static const int kValueOffset
static const int kCacheStampOffset
static const int kFingerOffset
static const int kSharedFunctionInfoOffset
static const int kLiteralsOffset
static const int kCodeEntryOffset
static const int kResultDonePropertyOffset
static const int kFunctionOffset
static const int kGeneratorClosed
static const int kResultValuePropertyOffset
static const int kGeneratorExecuting
static const int kOperandStackOffset
static const int kReceiverOffset
static const int kContextOffset
static const int kContinuationOffset
static const int kInitialMaxFastElementArray
static const int kPropertiesOffset
static const int kElementsOffset
static const int kInObjectFieldCount
static const int kValueOffset
static const int kLocal0Offset
static const int kFunctionOffset
static const Register ReceiverRegister()
static const Register NameRegister()
SmiIndex SmiToIndex(Register dst, Register src, int shift)
Condition CheckNonNegativeSmi(Register src)
Handle< Object > CodeObject()
static const int kIsUndetectable
static const int kBitFieldOffset
static const int kStringWrapperSafeForDefaultValueOf
static const int kInstanceTypeOffset
static const int kBitField2Offset
static const int kConstructorOffset
static const int kPrototypeOffset
static const int kHashShift
static const int kHashFieldOffset
static void MaybeCallEntryHook(MacroAssembler *masm)
static const int kNoPosition
Scope * outer_scope() const
int num_parameters() const
VariableDeclaration * function() const
int ContextChainLength(Scope *scope)
void VisitIllegalRedeclaration(AstVisitor *visitor)
Scope * DeclarationScope()
Variable * arguments() const
Variable * parameter(int index) const
static const int kHeaderSize
static const int kFormalParameterCountOffset
static const int kInstanceClassNameOffset
static Smi * FromInt(int value)
static bool IsValid(intptr_t value)
static const int kContextOffset
static const int kContextOffset
static const int kExpressionsOffset
static const int kCallerSPOffset
static const int kMarkerOffset
static const int kCallerFPOffset
static const Register ReceiverRegister()
static const Register NameRegister()
static const Register ValueRegister()
static const unsigned int kContainsCachedArrayIndexMask
static const int kLengthOffset
bool Equals(String *other)
static Handle< Code > GetUninitialized(Isolate *isolate)
static TypeFeedbackId None()
static Handle< Object > MegamorphicSentinel(Isolate *isolate)
static const Register SlotRegister()
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS 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 mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction pairs(ARM only)") DEFINE_BOOL(enable_unaligned_accesses
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS 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 enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
static int Push(SpecialRPOStackFrame *stack, int depth, BasicBlock *child, int unvisited)
Vector< const char > CStrVector(const char *data)
const uint32_t kStringEncodingMask
MemOperand ContextOperand(Register context, int index)
@ DONT_TRACK_ALLOCATION_SITE
kFeedbackVectorOffset kHiddenPrototypeBit kReadOnlyPrototypeBit kDoNotCacheBit kIsTopLevelBit kAllowLazyCompilationWithoutContext has_duplicate_parameters
const Register kScratchRegister
static LifetimePosition Min(LifetimePosition a, LifetimePosition b)
bool IsDeclaredVariableMode(VariableMode mode)
const uint32_t kTwoByteStringTag
Operand FieldOperand(Register object, int offset)
const int kPointerSizeLog2
const uint32_t kStringTag
@ LAST_NONCALLABLE_SPEC_OBJECT_TYPE
@ NUM_OF_CALLABLE_SPEC_OBJECT_TYPES
@ FIRST_NONCALLABLE_SPEC_OBJECT_TYPE
const uint32_t kOneByteStringTag
bool IsImmutableVariableMode(VariableMode mode)
Condition NegateCondition(Condition cond)
static LifetimePosition Max(LifetimePosition a, LifetimePosition b)
const uint32_t kStringRepresentationMask
kFeedbackVectorOffset flag
MemOperand GlobalObjectOperand()
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
const intptr_t kSmiTagMask
@ RECORD_CONSTRUCTOR_TARGET
const uint32_t kIsNotStringMask
bool IsAligned(T value, U alignment)
@ PRESERVE_SOURCE_REGISTER
void CopyBytes(uint8_t *target, uint8_t *source)
bool IsFastObjectElementsKind(ElementsKind kind)
Debugger support for the V8 JavaScript engine.
bool is(Register reg) const