7 #if V8_TARGET_ARCH_IA32
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 distance = Label::kFar) {
45 void EmitJumpIfSmi(Register reg,
47 Label::Distance distance = Label::kFar) {
49 EmitJump(
carry, target, distance);
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 __ test(
eax, Immediate(delta_to_patch_site));
67 void EmitJump(
Condition cc, Label* target, Label::Distance distance) {
68 DCHECK(!patch_site_.is_bound() && !info_emitted_);
70 __ bind(&patch_site_);
71 __ j(
cc, target, distance);
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 int receiver_offset = (info->scope()->num_parameters() + 1) *
kPointerSize;
121 __ mov(
ecx, Operand(
esp, receiver_offset));
123 __ cmp(
ecx, isolate()->factory()->undefined_value());
129 __ mov(Operand(
esp, receiver_offset),
ecx);
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 __ push(Immediate(isolate()->factory()->undefined_value()));
149 }
else if (locals_count > 1) {
150 if (locals_count >= 128) {
154 ExternalReference stack_limit =
155 ExternalReference::address_of_real_stack_limit(isolate());
156 __ cmp(
ecx, Operand::StaticVariable(stack_limit));
161 __ mov(
eax, Immediate(isolate()->factory()->undefined_value()));
162 const int kMaxPushes = 32;
163 if (locals_count >= kMaxPushes) {
164 int loop_iterations = locals_count / kMaxPushes;
165 __ mov(
ecx, loop_iterations);
167 __ bind(&loop_header);
169 for (
int i = 0;
i < kMaxPushes;
i++) {
175 int remaining = locals_count % kMaxPushes;
177 for (
int i = 0;
i < remaining;
i++) {
183 bool function_in_register =
true;
187 if (heap_slots > 0) {
188 Comment cmnt(
masm_,
"[ Allocate context");
189 bool need_write_barrier =
true;
191 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
193 __ Push(info->scope()->GetScopeInfo());
194 __ CallRuntime(Runtime::kNewGlobalContext, 2);
195 }
else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
196 FastNewContextStub stub(isolate(), heap_slots);
199 need_write_barrier =
false;
202 __ CallRuntime(Runtime::kNewFunctionContext, 1);
204 function_in_register =
false;
211 int num_parameters = info->scope()->num_parameters();
212 for (
int i = 0;
i < num_parameters;
i++) {
214 if (var->IsContextSlot()) {
218 __ mov(
eax, Operand(
ebp, parameter_offset));
221 __ mov(Operand(
esi, context_offset),
eax);
223 if (need_write_barrier) {
224 __ RecordWriteContextSlot(
esi,
229 }
else if (FLAG_debug_code) {
231 __ JumpIfInNewSpace(
esi,
eax, &done, Label::kNear);
232 __ Abort(kExpectedNewSpaceObject);
240 if (arguments !=
NULL) {
242 Comment cmnt(
masm_,
"[ Allocate arguments object");
243 if (function_in_register) {
249 int num_parameters = info->scope()->num_parameters();
267 ArgumentsAccessStub stub(isolate(), type);
274 __ CallRuntime(Runtime::kTraceEnter, 0);
279 if (
scope()->HasIllegalRedeclaration()) {
280 Comment cmnt(
masm_,
"[ Declarations");
285 { Comment cmnt(
masm_,
"[ Declarations");
288 if (
scope()->is_function_scope() &&
scope()->
function() !=
NULL) {
293 VisitVariableDeclaration(
function);
298 { Comment cmnt(
masm_,
"[ Stack check");
301 ExternalReference stack_limit
302 = ExternalReference::address_of_stack_limit(isolate());
303 __ cmp(
esp, Operand::StaticVariable(stack_limit));
309 { Comment cmnt(
masm_,
"[ Body");
311 VisitStatements(
function()->body());
318 { Comment cmnt(
masm_,
"[ return <undefined>;");
319 __ mov(
eax, isolate()->factory()->undefined_value());
338 int reset_value = FLAG_interrupt_budget;
346 Label* back_edge_target) {
347 Comment cmnt(
masm_,
"[ Back edge bookkeeping");
350 DCHECK(back_edge_target->is_bound());
353 Max(1, distance / kCodeSizeMultiplier));
375 Comment cmnt(
masm_,
"[ Return sequence");
383 __ CallRuntime(Runtime::kTraceExit, 1);
388 weight = FLAG_interrupt_budget / FLAG_self_opt_count;
392 Max(1, distance / kCodeSizeMultiplier));
398 __ call(isolate()->builtins()->InterruptCheck(),
405 Label check_exit_codesize;
417 __ Ret(arguments_bytes,
ecx);
428 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
433 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
439 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
449 codegen()->PrepareForBailoutBeforeSplit(condition(),
false,
NULL,
NULL);
450 codegen()->DoTest(
this);
481 Handle<Object> lit)
const {
492 __ SafePush(Immediate(lit));
494 __ push(Immediate(lit));
500 codegen()->PrepareForBailoutBeforeSplit(condition(),
504 DCHECK(!lit->IsUndetectableObject());
505 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
506 if (false_label_ != fall_through_)
__ jmp(false_label_);
507 }
else if (lit->IsTrue() || lit->IsJSObject()) {
508 if (true_label_ != fall_through_)
__ jmp(true_label_);
509 }
else if (lit->IsString()) {
510 if (String::cast(*lit)->length() == 0) {
511 if (false_label_ != fall_through_)
__ jmp(false_label_);
513 if (true_label_ != fall_through_)
__ jmp(true_label_);
515 }
else if (lit->IsSmi()) {
516 if (Smi::cast(*lit)->value() == 0) {
517 if (false_label_ != fall_through_)
__ jmp(false_label_);
519 if (true_label_ != fall_through_)
__ jmp(true_label_);
524 codegen()->DoTest(
this);
530 Register reg)
const {
538 Register reg)
const {
546 Register reg)
const {
548 if (count > 1)
__ Drop(count - 1);
549 __ mov(Operand(
esp, 0), reg);
554 Register reg)
const {
559 codegen()->PrepareForBailoutBeforeSplit(condition(),
false,
NULL,
NULL);
560 codegen()->DoTest(
this);
565 Label* materialize_false)
const {
566 DCHECK(materialize_true == materialize_false);
567 __ bind(materialize_true);
572 Label* materialize_true,
573 Label* materialize_false)
const {
575 __ bind(materialize_true);
577 __ jmp(&done, Label::kNear);
578 __ bind(materialize_false);
585 Label* materialize_true,
586 Label* materialize_false)
const {
588 __ bind(materialize_true);
589 __ push(Immediate(isolate()->factory()->true_value()));
590 __ jmp(&done, Label::kNear);
591 __ bind(materialize_false);
592 __ push(Immediate(isolate()->factory()->false_value()));
598 Label* materialize_false)
const {
599 DCHECK(materialize_true == true_label_);
600 DCHECK(materialize_false == false_label_);
609 Handle<Object> value =
flag
610 ? isolate()->factory()->true_value()
611 : isolate()->factory()->false_value();
617 Handle<Object> value =
flag
618 ? isolate()->factory()->true_value()
619 : isolate()->factory()->false_value();
620 __ push(Immediate(value));
625 codegen()->PrepareForBailoutBeforeSplit(condition(),
630 if (true_label_ != fall_through_)
__ jmp(true_label_);
632 if (false_label_ != fall_through_)
__ jmp(false_label_);
640 Label* fall_through) {
642 CallIC(ic, condition->test_id());
652 Label* fall_through) {
653 if (if_false == fall_through) {
655 }
else if (if_true == fall_through) {
665 DCHECK(var->IsStackAllocated());
669 if (var->IsParameter()) {
674 return Operand(
ebp, offset);
679 DCHECK(var->IsContextSlot() || var->IsStackAllocated());
680 if (var->IsContextSlot()) {
682 __ LoadContext(scratch, context_chain_length);
691 DCHECK(var->IsContextSlot() || var->IsStackAllocated());
693 __ mov(dest, location);
701 DCHECK(var->IsContextSlot() || var->IsStackAllocated());
702 DCHECK(!scratch0.is(src));
703 DCHECK(!scratch0.is(scratch1));
704 DCHECK(!scratch1.is(src));
706 __ mov(location, src);
709 if (var->IsContextSlot()) {
718 bool should_normalize,
727 if (should_normalize)
__ jmp(&skip, Label::kNear);
729 if (should_normalize) {
730 __ cmp(
eax, isolate()->factory()->true_value());
743 __ cmp(
ebx, isolate()->factory()->with_context_map());
745 __ cmp(
ebx, isolate()->factory()->catch_context_map());
751 void FullCodeGenerator::VisitVariableDeclaration(
752 VariableDeclaration* declaration) {
756 VariableProxy* proxy = declaration->proxy();
758 Variable* variable = proxy->var();
760 switch (variable->location()) {
762 globals_->Add(variable->name(), zone());
763 globals_->Add(variable->binding_needs_init()
764 ? isolate()->factory()->the_hole_value()
765 : isolate()->factory()->undefined_value(), zone());
771 Comment cmnt(
masm_,
"[ VariableDeclaration");
773 Immediate(isolate()->factory()->the_hole_value()));
779 Comment cmnt(
masm_,
"[ VariableDeclaration");
782 Immediate(isolate()->factory()->the_hole_value()));
789 Comment cmnt(
masm_,
"[ VariableDeclaration");
791 __ push(Immediate(variable->name()));
802 __ push(Immediate(isolate()->factory()->the_hole_value()));
806 __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
813 void FullCodeGenerator::VisitFunctionDeclaration(
814 FunctionDeclaration* declaration) {
815 VariableProxy* proxy = declaration->proxy();
816 Variable* variable = proxy->var();
817 switch (variable->location()) {
819 globals_->Add(variable->name(), zone());
820 Handle<SharedFunctionInfo>
function =
823 if (
function.is_null())
return SetStackOverflow();
830 Comment cmnt(
masm_,
"[ FunctionDeclaration");
837 Comment cmnt(
masm_,
"[ FunctionDeclaration");
842 __ RecordWriteContextSlot(
esi,
854 Comment cmnt(
masm_,
"[ FunctionDeclaration");
856 __ push(Immediate(variable->name()));
859 __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
866 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
867 Variable* variable = declaration->proxy()->var();
869 DCHECK(variable->interface()->IsFrozen());
871 Comment cmnt(
masm_,
"[ ModuleDeclaration");
882 __ RecordWriteContextSlot(
esi,
892 Visit(declaration->module());
896 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
897 VariableProxy* proxy = declaration->proxy();
898 Variable* variable = proxy->var();
899 switch (variable->location()) {
905 Comment cmnt(
masm_,
"[ ImportDeclaration");
919 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
929 __ CallRuntime(Runtime::kDeclareGlobals, 3);
937 __ CallRuntime(Runtime::kDeclareModules, 1);
942 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
943 Comment cmnt(
masm_,
"[ SwitchStatement");
944 Breakable nested_statement(
this, stmt);
951 ZoneList<CaseClause*>* clauses = stmt->cases();
952 CaseClause* default_clause =
NULL;
956 for (
int i = 0;
i < clauses->length();
i++) {
957 CaseClause* clause = clauses->at(
i);
958 clause->body_target()->Unuse();
961 if (clause->is_default()) {
962 default_clause = clause;
966 Comment cmnt(
masm_,
"[ Case comparison");
976 JumpPatchSite patch_site(
masm_);
977 if (inline_smi_code) {
981 patch_site.EmitJumpIfNotSmi(
ecx, &slow_case, Label::kNear);
986 __ jmp(clause->body_target());
993 CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
994 CallIC(ic, clause->CompareId());
995 patch_site.EmitPatchInfo();
998 __ jmp(&skip, Label::kNear);
1000 __ cmp(
eax, isolate()->factory()->true_value());
1003 __ jmp(clause->body_target());
1009 __ jmp(clause->body_target());
1014 __ bind(&next_test);
1016 if (default_clause ==
NULL) {
1017 __ jmp(nested_statement.break_label());
1019 __ jmp(default_clause->body_target());
1023 for (
int i = 0;
i < clauses->length();
i++) {
1024 Comment cmnt(
masm_,
"[ Case body");
1025 CaseClause* clause = clauses->at(
i);
1026 __ bind(clause->body_target());
1028 VisitStatements(clause->statements());
1031 __ bind(nested_statement.break_label());
1036 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1037 Comment cmnt(
masm_,
"[ ForInStatement");
1038 int slot = stmt->ForInFeedbackSlot();
1043 ForIn loop_statement(
this, stmt);
1049 __ cmp(
eax, isolate()->factory()->undefined_value());
1051 __ cmp(
eax, isolate()->factory()->null_value());
1057 Label convert, done_convert;
1058 __ JumpIfSmi(
eax, &convert, Label::kNear);
1064 __ bind(&done_convert);
1068 Label call_runtime, use_cache, fixed_array;
1077 __ CheckEnumCache(&call_runtime);
1080 __ jmp(&use_cache, Label::kNear);
1083 __ bind(&call_runtime);
1085 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1087 isolate()->factory()->meta_map());
1092 Label no_descriptors;
1093 __ bind(&use_cache);
1099 __ LoadInstanceDescriptors(
eax,
ecx);
1110 __ bind(&no_descriptors);
1116 __ bind(&fixed_array);
1129 __ bind(&non_proxy);
1156 __ j(
equal, &update_each, Label::kNear);
1162 __ j(
zero, &update_each);
1171 __ j(
equal, loop_statement.continue_label());
1176 __ bind(&update_each);
1179 { EffectContext
context(
this);
1184 Visit(stmt->body());
1188 __ bind(loop_statement.continue_label());
1195 __ bind(loop_statement.break_label());
1205 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1206 Comment cmnt(
masm_,
"[ ForOfStatement");
1209 Iteration loop_statement(
this, stmt);
1216 __ bind(loop_statement.continue_label());
1222 Label result_not_done;
1224 loop_statement.break_label(),
1227 __ bind(&result_not_done);
1233 Visit(stmt->body());
1238 __ jmp(loop_statement.continue_label());
1242 __ bind(loop_statement.break_label());
1255 if (!FLAG_always_opt &&
1256 !FLAG_prepare_always_opt &&
1258 scope()->is_function_scope() &&
1259 info->num_literals() == 0) {
1260 FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
1261 __ mov(
ebx, Immediate(info));
1265 __ push(Immediate(info));
1266 __ push(Immediate(pretenure
1267 ? isolate()->factory()->true_value()
1268 : isolate()->factory()->false_value()));
1269 __ CallRuntime(Runtime::kNewClosure, 3);
1275 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
1276 Comment cmnt(
masm_,
"[ VariableProxy");
1282 Comment cnmt(
masm_,
"[ SuperReference ");
1287 Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
1292 __ cmp(
eax, isolate()->factory()->undefined_value());
1295 __ CallRuntime(Runtime::kThrowNonMethodError, 0);
1304 Register temp =
edx;
1308 if (s->num_heap_slots() > 0) {
1309 if (s->calls_sloppy_eval()) {
1323 if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope())
break;
1324 s = s->outer_scope();
1327 if (s !=
NULL && s->is_eval_scope()) {
1337 Immediate(isolate()->factory()->native_context_map()));
1338 __ j(
equal, &fast, Label::kNear);
1352 if (FLAG_vector_ics) {
1354 Immediate(
Smi::FromInt(proxy->VariableFeedbackSlot())));
1367 DCHECK(var->IsContextSlot());
1369 Register temp =
ebx;
1372 if (s->num_heap_slots() > 0) {
1373 if (s->calls_sloppy_eval()) {
1404 Variable* var = proxy->var();
1409 Variable* local = var->local_if_not_shadowed();
1411 if (local->mode() ==
LET || local->mode() ==
CONST ||
1413 __ cmp(
eax, isolate()->factory()->the_hole_value());
1416 __ mov(
eax, isolate()->factory()->undefined_value());
1418 __ push(Immediate(var->name()));
1419 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1430 Variable* var = proxy->var();
1434 switch (var->location()) {
1436 Comment cmnt(
masm_,
"[ Global variable");
1439 if (FLAG_vector_ics) {
1441 Immediate(
Smi::FromInt(proxy->VariableFeedbackSlot())));
1451 Comment cmnt(
masm_, var->IsContextSlot() ?
"[ Context variable"
1452 :
"[ Stack variable");
1453 if (var->binding_needs_init()) {
1477 bool skip_init_check;
1478 if (var->scope()->DeclarationScope() !=
scope()->DeclarationScope()) {
1479 skip_init_check =
false;
1485 var->initializer_position() < proxy->position();
1488 if (!skip_init_check) {
1492 __ cmp(
eax, isolate()->factory()->the_hole_value());
1494 if (var->mode() ==
LET || var->mode() ==
CONST) {
1497 __ push(Immediate(var->name()));
1498 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1502 __ mov(
eax, isolate()->factory()->undefined_value());
1514 Comment cmnt(
masm_,
"[ Lookup variable");
1521 __ push(Immediate(var->name()));
1522 __ CallRuntime(Runtime::kLoadLookupSlot, 2);
1531 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1532 Comment cmnt(
masm_,
"[ RegExpLiteral");
1541 int literal_offset =
1544 __ cmp(
ebx, isolate()->factory()->undefined_value());
1551 __ push(Immediate(expr->pattern()));
1552 __ push(Immediate(expr->flags()));
1553 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1556 __ bind(&materialized);
1558 Label allocated, runtime_allocate;
1562 __ bind(&runtime_allocate);
1565 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1568 __ bind(&allocated);
1586 if (expression ==
NULL) {
1587 __ push(Immediate(isolate()->factory()->null_value()));
1594 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1595 Comment cmnt(
masm_,
"[ ObjectLiteral");
1597 expr->BuildConstantProperties(isolate());
1598 Handle<FixedArray> constant_properties = expr->constant_properties();
1599 int flags = expr->fast_elements()
1600 ? ObjectLiteral::kFastElements
1601 : ObjectLiteral::kNoFlags;
1602 flags |= expr->has_function()
1603 ? ObjectLiteral::kHasFunction
1604 : ObjectLiteral::kNoFlags;
1605 int properties_count = constant_properties->length() / 2;
1606 if (expr->may_store_doubles() || expr->depth() > 1 ||
1607 masm()->serializer_enabled() ||
1608 flags != ObjectLiteral::kFastElements ||
1613 __ push(Immediate(constant_properties));
1615 __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
1620 __ mov(
ecx, Immediate(constant_properties));
1622 FastCloneShallowObjectStub stub(isolate(), properties_count);
1628 bool result_saved =
false;
1633 expr->CalculateEmitStore(zone());
1635 AccessorTable accessor_table(zone());
1636 for (
int i = 0;
i < expr->properties()->length();
i++) {
1637 ObjectLiteral::Property*
property = expr->properties()->at(
i);
1638 if (property->IsCompileTimeValue())
continue;
1640 Literal* key =
property->key();
1641 Expression* value =
property->value();
1642 if (!result_saved) {
1644 result_saved =
true;
1646 switch (property->kind()) {
1649 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1652 case ObjectLiteral::Property::COMPUTED:
1653 if (key->value()->IsInternalizedString()) {
1654 if (property->emit_store()) {
1666 __ push(Operand(
esp, 0));
1669 if (property->emit_store()) {
1671 __ CallRuntime(Runtime::kSetProperty, 4);
1676 case ObjectLiteral::Property::PROTOTYPE:
1677 __ push(Operand(
esp, 0));
1679 if (property->emit_store()) {
1680 __ CallRuntime(Runtime::kSetPrototype, 2);
1685 case ObjectLiteral::Property::GETTER:
1686 accessor_table.lookup(key)->second->getter = value;
1688 case ObjectLiteral::Property::SETTER:
1689 accessor_table.lookup(key)->second->setter = value;
1696 for (AccessorTable::Iterator it = accessor_table.begin();
1697 it != accessor_table.end();
1699 __ push(Operand(
esp, 0));
1704 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
1707 if (expr->has_function()) {
1709 __ push(Operand(
esp, 0));
1710 __ CallRuntime(Runtime::kToFastProperties, 1);
1721 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1722 Comment cmnt(
masm_,
"[ ArrayLiteral");
1724 expr->BuildConstantElements(isolate());
1725 int flags = expr->depth() == 1
1726 ? ArrayLiteral::kShallowElements
1727 : ArrayLiteral::kNoFlags;
1729 ZoneList<Expression*>* subexprs = expr->values();
1730 int length = subexprs->length();
1731 Handle<FixedArray> constant_elements = expr->constant_elements();
1732 DCHECK_EQ(2, constant_elements->length());
1734 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1735 bool has_constant_fast_elements =
1737 Handle<FixedArrayBase> constant_elements_values(
1738 FixedArrayBase::cast(constant_elements->get(1)));
1741 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
1751 __ push(Immediate(constant_elements));
1753 __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
1758 __ mov(
ecx, Immediate(constant_elements));
1759 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1763 bool result_saved =
false;
1767 for (
int i = 0;
i < length;
i++) {
1768 Expression* subexpr = subexprs->at(
i);
1773 if (!result_saved) {
1776 result_saved =
true;
1796 StoreArrayLiteralElementStub stub(isolate());
1812 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1813 DCHECK(expr->target()->IsValidReferenceExpression());
1815 Comment cmnt(
masm_,
"[ Assignment");
1823 NAMED_SUPER_PROPERTY
1826 Property*
property = expr->target()->AsProperty();
1827 if (property !=
NULL) {
1828 assign_type = (
property->key()->IsPropertyName())
1829 ? (property->IsSuperAccess() ? NAMED_SUPER_PROPERTY
1835 switch (assign_type) {
1839 case NAMED_SUPER_PROPERTY:
1843 if (expr->is_compound()) {
1849 if (expr->is_compound()) {
1858 if (expr->is_compound()) {
1873 if (expr->is_compound()) {
1874 AccumulatorValueContext result_context(
this);
1875 { AccumulatorValueContext left_operand_context(
this);
1876 switch (assign_type) {
1881 case NAMED_SUPER_PROPERTY:
1924 switch (assign_type) {
1934 case NAMED_SUPER_PROPERTY:
1944 void FullCodeGenerator::VisitYield(Yield* expr) {
1945 Comment cmnt(
masm_,
"[ Yield");
1950 switch (expr->yield_kind()) {
1951 case Yield::kSuspend:
1956 case Yield::kInitial: {
1957 Label suspend, continuation, post_runtime, resume;
1961 __ bind(&continuation);
1977 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1980 __ bind(&post_runtime);
1989 case Yield::kFinal: {
2001 case Yield::kDelegating: {
2008 Label l_catch, l_try, l_suspend, l_continuation, l_resume;
2009 Label l_next, l_call, l_loop;
2014 __ mov(
eax, isolate()->factory()->undefined_value());
2020 __ mov(load_name, isolate()->factory()->throw_string());
2031 __ PushTryHandler(StackHandler::CATCH, expr->index());
2035 __ bind(&l_continuation);
2037 __ bind(&l_suspend);
2038 const int generator_object_depth =
kPointerSize + handler_size;
2039 __ mov(
eax, Operand(
esp, generator_object_depth));
2048 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2059 __ mov(load_name, isolate()->factory()->next_string());
2067 if (FLAG_vector_ics) {
2069 Immediate(
Smi::FromInt(expr->KeyedLoadFeedbackSlot())));
2071 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
2084 __ Move(load_receiver,
eax);
2086 isolate()->factory()->done_string());
2087 if (FLAG_vector_ics) {
2098 __ pop(load_receiver);
2100 isolate()->factory()->value_string());
2101 if (FLAG_vector_ics) {
2125 Label wrong_state, closed_state, done;
2131 __ j(
less, &wrong_state);
2144 __ mov(
ecx, isolate()->factory()->the_hole_value());
2145 Label push_argument_holes, push_frame;
2146 __ bind(&push_argument_holes);
2150 __ jmp(&push_argument_holes);
2155 __ bind(&push_frame);
2156 __ call(&resume_frame);
2158 __ bind(&resume_frame);
2173 __ cmp(
edx, Immediate(0));
2182 __ bind(&slow_resume);
2187 Label push_operand_holes, call_resume;
2188 __ bind(&push_operand_holes);
2189 __ sub(
edx, Immediate(1));
2192 __ jmp(&push_operand_holes);
2193 __ bind(&call_resume);
2197 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
2199 __ Abort(kGeneratorFailedToResume);
2202 __ bind(&closed_state);
2205 __ push(Immediate(isolate()->factory()->undefined_value()));
2211 __ CallRuntime(Runtime::kThrow, 1);
2216 __ bind(&wrong_state);
2218 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
2229 Handle<Map>
map(isolate()->native_context()->iterator_result_map());
2234 __ bind(&gc_required);
2236 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2240 __ bind(&allocated);
2243 __ mov(
edx, isolate()->factory()->ToBoolean(done));
2247 isolate()->factory()->empty_fixed_array());
2249 isolate()->factory()->empty_fixed_array());
2262 Literal* key = prop->key()->AsLiteral();
2263 DCHECK(!key->value()->IsSmi());
2264 DCHECK(!prop->IsSuperAccess());
2267 if (FLAG_vector_ics) {
2269 Immediate(
Smi::FromInt(prop->PropertyFeedbackSlot())));
2280 Literal* key = prop->key()->AsLiteral();
2281 DCHECK(!key->value()->IsSmi());
2282 DCHECK(prop->IsSuperAccess());
2284 __ push(Immediate(key->value()));
2285 __ CallRuntime(Runtime::kLoadFromSuper, 3);
2291 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
2292 if (FLAG_vector_ics) {
2294 Immediate(
Smi::FromInt(prop->PropertyFeedbackSlot())));
2297 CallIC(ic, prop->PropertyFeedbackId());
2306 Expression* right) {
2309 Label smi_case, done, stub_call;
2313 JumpPatchSite patch_site(
masm_);
2314 patch_site.EmitJumpIfSmi(
eax, &smi_case, Label::kNear);
2316 __ bind(&stub_call);
2318 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op,
mode).code();
2319 CallIC(code, expr->BinaryOperationFeedbackId());
2320 patch_site.EmitPatchInfo();
2321 __ jmp(&done, Label::kNear);
2339 __ cmp(
eax, 0xc0000000);
2343 __ bind(&result_ok);
2352 __ test(
eax, Immediate(0xc0000000));
2356 __ bind(&result_ok);
2382 case Token::BIT_AND:
2385 case Token::BIT_XOR:
2401 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op,
mode).code();
2402 JumpPatchSite patch_site(
masm_);
2403 CallIC(code, expr->BinaryOperationFeedbackId());
2404 patch_site.EmitPatchInfo();
2410 DCHECK(expr->IsValidReferenceExpression());
2416 Property* prop = expr->AsProperty();
2418 assign_type = (prop->key()->IsPropertyName())
2423 switch (assign_type) {
2425 Variable* var = expr->AsVariableProxy()->var();
2436 prop->key()->AsLiteral()->value());
2448 CodeFactory::KeyedStoreIC(isolate(),
strict_mode()).code();
2459 __ mov(location,
eax);
2460 if (var->IsContextSlot()) {
2470 if (var->IsUnallocated()) {
2476 }
else if (op == Token::INIT_CONST_LEGACY) {
2478 DCHECK(!var->IsParameter());
2479 if (var->IsLookupSlot()) {
2482 __ push(Immediate(var->name()));
2483 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3);
2485 DCHECK(var->IsStackLocal() || var->IsContextSlot());
2488 __ mov(
edx, location);
2489 __ cmp(
edx, isolate()->factory()->the_hole_value());
2495 }
else if (var->mode() ==
LET && op != Token::INIT_LET) {
2497 DCHECK(!var->IsLookupSlot());
2498 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2501 __ mov(
edx, location);
2502 __ cmp(
edx, isolate()->factory()->the_hole_value());
2504 __ push(Immediate(var->name()));
2505 __ CallRuntime(Runtime::kThrowReferenceError, 1);
2509 }
else if (!var->is_const_mode() || op == Token::INIT_CONST) {
2510 if (var->IsLookupSlot()) {
2514 __ push(Immediate(var->name()));
2516 __ CallRuntime(Runtime::kStoreLookupSlot, 4);
2520 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2524 __ mov(
edx, location);
2525 __ cmp(
edx, isolate()->factory()->the_hole_value());
2526 __ Check(
equal, kLetBindingReInitialization);
2540 Property* prop = expr->target()->AsProperty();
2542 DCHECK(prop->key()->IsLiteral());
2558 Property* prop = expr->target()->AsProperty();
2560 Literal* key = prop->key()->AsLiteral();
2564 __ push(Immediate(key->value()));
2566 : Runtime::kStoreToSuper_Sloppy),
2583 Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(),
strict_mode()).code();
2584 CallIC(ic, expr->AssignmentFeedbackId());
2591 void FullCodeGenerator::VisitProperty(Property* expr) {
2592 Comment cmnt(
masm_,
"[ Property");
2593 Expression* key = expr->key();
2595 if (key->IsPropertyName()) {
2596 if (!expr->IsSuperAccess()) {
2620 TypeFeedbackId ast_id) {
2628 Expression* callee = expr->expression();
2630 CallICState::CallType call_type =
2631 callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD;
2633 if (call_type == CallICState::FUNCTION) {
2634 { StackValueContext
context(
this);
2640 __ push(Immediate(isolate()->factory()->undefined_value()));
2643 DCHECK(callee->IsProperty());
2644 DCHECK(!callee->AsProperty()->IsSuperAccess());
2649 __ push(Operand(
esp, 0));
2658 Expression* callee = expr->expression();
2659 DCHECK(callee->IsProperty());
2660 Property* prop = callee->AsProperty();
2661 DCHECK(prop->IsSuperAccess());
2664 Literal* key = prop->key()->AsLiteral();
2665 DCHECK(!key->value()->IsSmi());
2667 SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
2674 __ push(Immediate(key->value()));
2681 __ CallRuntime(Runtime::kLoadFromSuper, 3);
2689 EmitCall(expr, CallICState::METHOD);
2699 Expression* callee = expr->expression();
2702 DCHECK(callee->IsProperty());
2709 __ push(Operand(
esp, 0));
2712 EmitCall(expr, CallICState::METHOD);
2718 ZoneList<Expression*>* args = expr->arguments();
2719 int arg_count = args->length();
2720 { PreservePositionScope
scope(
masm()->positions_recorder());
2721 for (
int i = 0;
i < arg_count;
i++) {
2729 isolate(), arg_count, call_type);
2747 if (arg_count > 0) {
2750 __ push(Immediate(isolate()->factory()->undefined_value()));
2762 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
2766 void FullCodeGenerator::VisitCall(Call* expr) {
2770 expr->return_is_recorded_ =
false;
2773 Comment cmnt(
masm_,
"[ Call");
2774 Expression* callee = expr->expression();
2775 Call::CallType call_type = expr->GetCallType(isolate());
2777 if (call_type == Call::POSSIBLY_EVAL_CALL) {
2781 ZoneList<Expression*>* args = expr->arguments();
2782 int arg_count = args->length();
2783 { PreservePositionScope pos_scope(
masm()->positions_recorder());
2786 __ push(Immediate(isolate()->factory()->undefined_value()));
2788 for (
int i = 0;
i < arg_count;
i++) {
2812 }
else if (call_type == Call::GLOBAL_CALL) {
2815 }
else if (call_type == Call::LOOKUP_SLOT_CALL) {
2817 VariableProxy* proxy = callee->AsVariableProxy();
2819 { PreservePositionScope
scope(
masm()->positions_recorder());
2828 __ push(Immediate(proxy->name()));
2829 __ CallRuntime(Runtime::kLoadLookupSlot, 2);
2835 if (done.is_linked()) {
2837 __ jmp(&call, Label::kNear);
2843 __ push(Immediate(isolate()->factory()->undefined_value()));
2851 }
else if (call_type == Call::PROPERTY_CALL) {
2852 Property*
property = callee->AsProperty();
2853 bool is_named_call =
property->key()->IsPropertyName();
2855 if (property->IsSuperAccess() && is_named_call) {
2859 PreservePositionScope
scope(
masm()->positions_recorder());
2862 if (is_named_call) {
2869 DCHECK(call_type == Call::OTHER_CALL);
2871 { PreservePositionScope
scope(
masm()->positions_recorder());
2874 __ push(Immediate(isolate()->factory()->undefined_value()));
2881 DCHECK(expr->return_is_recorded_);
2886 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
2887 Comment cmnt(
masm_,
"[ CallNew");
2898 ZoneList<Expression*>* args = expr->arguments();
2899 int arg_count = args->length();
2900 for (
int i = 0;
i < arg_count;
i++) {
2909 __ Move(
eax, Immediate(arg_count));
2913 if (FLAG_pretenuring_call_new) {
2915 DCHECK(expr->AllocationSiteFeedbackSlot() ==
2916 expr->CallNewFeedbackSlot() + 1);
2929 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2930 ZoneList<Expression*>* args = expr->arguments();
2931 DCHECK(args->length() == 1);
2935 Label materialize_true, materialize_false;
2936 Label* if_true =
NULL;
2937 Label* if_false =
NULL;
2938 Label* fall_through =
NULL;
2939 context()->PrepareTest(&materialize_true, &materialize_false,
2940 &if_true, &if_false, &fall_through);
2944 Split(
zero, if_true, if_false, fall_through);
2946 context()->Plug(if_true, if_false);
2950 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
2951 ZoneList<Expression*>* args = expr->arguments();
2952 DCHECK(args->length() == 1);
2956 Label materialize_true, materialize_false;
2957 Label* if_true =
NULL;
2958 Label* if_false =
NULL;
2959 Label* fall_through =
NULL;
2960 context()->PrepareTest(&materialize_true, &materialize_false,
2961 &if_true, &if_false, &fall_through);
2965 Split(
zero, if_true, if_false, fall_through);
2967 context()->Plug(if_true, if_false);
2971 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
2972 ZoneList<Expression*>* args = expr->arguments();
2973 DCHECK(args->length() == 1);
2977 Label materialize_true, materialize_false;
2978 Label* if_true =
NULL;
2979 Label* if_false =
NULL;
2980 Label* fall_through =
NULL;
2981 context()->PrepareTest(&materialize_true, &materialize_false,
2982 &if_true, &if_false, &fall_through);
2984 __ JumpIfSmi(
eax, if_false);
2985 __ cmp(
eax, isolate()->factory()->null_value());
2999 context()->Plug(if_true, if_false);
3003 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
3004 ZoneList<Expression*>* args = expr->arguments();
3005 DCHECK(args->length() == 1);
3009 Label materialize_true, materialize_false;
3010 Label* if_true =
NULL;
3011 Label* if_false =
NULL;
3012 Label* fall_through =
NULL;
3013 context()->PrepareTest(&materialize_true, &materialize_false,
3014 &if_true, &if_false, &fall_through);
3016 __ JumpIfSmi(
eax, if_false);
3021 context()->Plug(if_true, if_false);
3025 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
3026 ZoneList<Expression*>* args = expr->arguments();
3027 DCHECK(args->length() == 1);
3031 Label materialize_true, materialize_false;
3032 Label* if_true =
NULL;
3033 Label* if_false =
NULL;
3034 Label* fall_through =
NULL;
3035 context()->PrepareTest(&materialize_true, &materialize_false,
3036 &if_true, &if_false, &fall_through);
3038 __ JumpIfSmi(
eax, if_false);
3045 context()->Plug(if_true, if_false);
3049 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
3050 CallRuntime* expr) {
3051 ZoneList<Expression*>* args = expr->arguments();
3052 DCHECK(args->length() == 1);
3056 Label materialize_true, materialize_false, skip_lookup;
3057 Label* if_true =
NULL;
3058 Label* if_false =
NULL;
3059 Label* fall_through =
NULL;
3060 context()->PrepareTest(&materialize_true, &materialize_false,
3061 &if_true, &if_false, &fall_through);
3063 __ AssertNotSmi(
eax);
3075 __ cmp(
ecx, isolate()->factory()->hash_table_map());
3081 Label entry, loop, done;
3084 __ NumberOfOwnDescriptors(
ecx,
ebx);
3088 __ LoadInstanceDescriptors(
ebx,
ebx);
3104 __ cmp(
edx, isolate()->factory()->value_of_string());
3120 __ bind(&skip_lookup);
3125 __ JumpIfSmi(
ecx, if_false);
3134 Split(
equal, if_true, if_false, fall_through);
3136 context()->Plug(if_true, if_false);
3140 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
3141 ZoneList<Expression*>* args = expr->arguments();
3142 DCHECK(args->length() == 1);
3146 Label materialize_true, materialize_false;
3147 Label* if_true =
NULL;
3148 Label* if_false =
NULL;
3149 Label* fall_through =
NULL;
3150 context()->PrepareTest(&materialize_true, &materialize_false,
3151 &if_true, &if_false, &fall_through);
3153 __ JumpIfSmi(
eax, if_false);
3156 Split(
equal, if_true, if_false, fall_through);
3158 context()->Plug(if_true, if_false);
3162 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
3163 ZoneList<Expression*>* args = expr->arguments();
3164 DCHECK(args->length() == 1);
3168 Label materialize_true, materialize_false;
3169 Label* if_true =
NULL;
3170 Label* if_false =
NULL;
3171 Label* fall_through =
NULL;
3172 context()->PrepareTest(&materialize_true, &materialize_false,
3173 &if_true, &if_false, &fall_through);
3183 Split(
equal, if_true, if_false, fall_through);
3185 context()->Plug(if_true, if_false);
3190 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
3191 ZoneList<Expression*>* args = expr->arguments();
3192 DCHECK(args->length() == 1);
3196 Label materialize_true, materialize_false;
3197 Label* if_true =
NULL;
3198 Label* if_false =
NULL;
3199 Label* fall_through =
NULL;
3200 context()->PrepareTest(&materialize_true, &materialize_false,
3201 &if_true, &if_false, &fall_through);
3203 __ JumpIfSmi(
eax, if_false);
3206 Split(
equal, if_true, if_false, fall_through);
3208 context()->Plug(if_true, if_false);
3212 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
3213 ZoneList<Expression*>* args = expr->arguments();
3214 DCHECK(args->length() == 1);
3218 Label materialize_true, materialize_false;
3219 Label* if_true =
NULL;
3220 Label* if_false =
NULL;
3221 Label* fall_through =
NULL;
3222 context()->PrepareTest(&materialize_true, &materialize_false,
3223 &if_true, &if_false, &fall_through);
3225 __ JumpIfSmi(
eax, if_false);
3228 Split(
equal, if_true, if_false, fall_through);
3230 context()->Plug(if_true, if_false);
3235 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
3236 DCHECK(expr->arguments()->length() == 0);
3238 Label materialize_true, materialize_false;
3239 Label* if_true =
NULL;
3240 Label* if_false =
NULL;
3241 Label* fall_through =
NULL;
3242 context()->PrepareTest(&materialize_true, &materialize_false,
3243 &if_true, &if_false, &fall_through);
3249 Label check_frame_marker;
3256 __ bind(&check_frame_marker);
3260 Split(
equal, if_true, if_false, fall_through);
3262 context()->Plug(if_true, if_false);
3266 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
3267 ZoneList<Expression*>* args = expr->arguments();
3268 DCHECK(args->length() == 2);
3274 Label materialize_true, materialize_false;
3275 Label* if_true =
NULL;
3276 Label* if_false =
NULL;
3277 Label* fall_through =
NULL;
3278 context()->PrepareTest(&materialize_true, &materialize_false,
3279 &if_true, &if_false, &fall_through);
3284 Split(
equal, if_true, if_false, fall_through);
3286 context()->Plug(if_true, if_false);
3290 void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
3291 ZoneList<Expression*>* args = expr->arguments();
3292 DCHECK(args->length() == 1);
3305 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
3306 DCHECK(expr->arguments()->length() == 0);
3328 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
3329 ZoneList<Expression*>* args = expr->arguments();
3330 DCHECK(args->length() == 1);
3331 Label done,
null,
function, non_function_constructor;
3336 __ JumpIfSmi(
eax, &
null);
3370 __ mov(
eax, isolate()->factory()->Function_string());
3374 __ bind(&non_function_constructor);
3375 __ mov(
eax, isolate()->factory()->Object_string());
3380 __ mov(
eax, isolate()->factory()->null_value());
3389 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
3391 SubStringStub stub(isolate());
3392 ZoneList<Expression*>* args = expr->arguments();
3393 DCHECK(args->length() == 3);
3402 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
3404 RegExpExecStub stub(isolate());
3405 ZoneList<Expression*>* args = expr->arguments();
3406 DCHECK(args->length() == 4);
3416 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
3417 ZoneList<Expression*>* args = expr->arguments();
3418 DCHECK(args->length() == 1);
3424 __ JumpIfSmi(
eax, &done, Label::kNear);
3435 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
3436 ZoneList<Expression*>* args = expr->arguments();
3437 DCHECK(args->length() == 2);
3439 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value()));
3443 Label runtime, done, not_date_object;
3444 Register
object =
eax;
3445 Register result =
eax;
3446 Register scratch =
ecx;
3448 __ JumpIfSmi(
object, ¬_date_object);
3452 if (index->value() == 0) {
3457 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
3458 __ mov(scratch, Operand::StaticVariable(stamp));
3466 __ PrepareCallCFunction(2, scratch);
3467 __ mov(Operand(
esp, 0),
object);
3469 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3473 __ bind(¬_date_object);
3474 __ CallRuntime(Runtime::kThrowNotDateError, 0);
3480 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
3481 ZoneList<Expression*>* args = expr->arguments();
3484 Register
string =
eax;
3485 Register index =
ebx;
3486 Register value =
ecx;
3495 if (FLAG_debug_code) {
3497 __ Check(
zero, kNonSmiValue);
3499 __ Check(
zero, kNonSmiValue);
3505 if (FLAG_debug_code) {
3507 __ EmitSeqStringSetCharCheck(
string, index, value, one_byte_seq_type);
3516 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
3517 ZoneList<Expression*>* args = expr->arguments();
3520 Register
string =
eax;
3521 Register index =
ebx;
3522 Register value =
ecx;
3530 if (FLAG_debug_code) {
3532 __ Check(
zero, kNonSmiValue);
3534 __ Check(
zero, kNonSmiValue);
3537 __ EmitSeqStringSetCharCheck(
string, index, value, two_byte_seq_type);
3549 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
3551 ZoneList<Expression*>* args = expr->arguments();
3552 DCHECK(args->length() == 2);
3562 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
3563 ZoneList<Expression*>* args = expr->arguments();
3564 DCHECK(args->length() == 2);
3572 __ JumpIfSmi(
ebx, &done, Label::kNear);
3591 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
3592 ZoneList<Expression*>* args = expr->arguments();
3598 NumberToStringStub stub(isolate());
3604 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
3605 ZoneList<Expression*>* args = expr->arguments();
3606 DCHECK(args->length() == 1);
3611 StringCharFromCodeGenerator generator(
eax,
ebx);
3612 generator.GenerateFast(
masm_);
3615 NopRuntimeCallHelper call_helper;
3616 generator.GenerateSlow(
masm_, call_helper);
3623 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
3624 ZoneList<Expression*>* args = expr->arguments();
3625 DCHECK(args->length() == 2);
3630 Register
object =
ebx;
3631 Register index =
eax;
3632 Register result =
edx;
3636 Label need_conversion;
3637 Label index_out_of_range;
3639 StringCharCodeAtGenerator generator(
object,
3644 &index_out_of_range,
3646 generator.GenerateFast(
masm_);
3649 __ bind(&index_out_of_range);
3652 __ Move(result, Immediate(isolate()->factory()->nan_value()));
3655 __ bind(&need_conversion);
3658 __ Move(result, Immediate(isolate()->factory()->undefined_value()));
3661 NopRuntimeCallHelper call_helper;
3662 generator.GenerateSlow(
masm_, call_helper);
3669 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
3670 ZoneList<Expression*>* args = expr->arguments();
3671 DCHECK(args->length() == 2);
3676 Register
object =
ebx;
3677 Register index =
eax;
3678 Register scratch =
edx;
3679 Register result =
eax;
3683 Label need_conversion;
3684 Label index_out_of_range;
3686 StringCharAtGenerator generator(
object,
3692 &index_out_of_range,
3694 generator.GenerateFast(
masm_);
3697 __ bind(&index_out_of_range);
3700 __ Move(result, Immediate(isolate()->factory()->empty_string()));
3703 __ bind(&need_conversion);
3709 NopRuntimeCallHelper call_helper;
3710 generator.GenerateSlow(
masm_, call_helper);
3717 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3718 ZoneList<Expression*>* args = expr->arguments();
3730 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3731 ZoneList<Expression*>* args = expr->arguments();
3737 StringCompareStub stub(isolate());
3743 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
3744 ZoneList<Expression*>* args = expr->arguments();
3745 DCHECK(args->length() >= 2);
3747 int arg_count = args->length() - 2;
3748 for (
int i = 0;
i < arg_count + 1; ++
i) {
3753 Label runtime, done;
3755 __ JumpIfSmi(
eax, &runtime);
3761 ParameterCount count(arg_count);
3768 __ CallRuntime(Runtime::kCall, args->length());
3775 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3777 RegExpConstructResultStub stub(isolate());
3778 ZoneList<Expression*>* args = expr->arguments();
3779 DCHECK(args->length() == 3);
3790 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3791 ZoneList<Expression*>* args = expr->arguments();
3795 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value();
3797 Handle<FixedArray> jsfunction_result_caches(
3798 isolate()->native_context()->jsfunction_result_caches());
3799 if (jsfunction_result_caches->length() <= cache_id) {
3800 __ Abort(kAttemptToUseUndefinedCache);
3801 __ mov(
eax, isolate()->factory()->undefined_value());
3809 Register cache =
ebx;
3818 Label done, not_found;
3828 __ bind(¬_found);
3832 __ CallRuntime(Runtime::kGetFromCache, 2);
3839 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3840 ZoneList<Expression*>* args = expr->arguments();
3841 DCHECK(args->length() == 1);
3845 __ AssertString(
eax);
3847 Label materialize_true, materialize_false;
3848 Label* if_true =
NULL;
3849 Label* if_false =
NULL;
3850 Label* fall_through =
NULL;
3851 context()->PrepareTest(&materialize_true, &materialize_false,
3852 &if_true, &if_false, &fall_through);
3857 Split(
zero, if_true, if_false, fall_through);
3859 context()->Plug(if_true, if_false);
3863 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3864 ZoneList<Expression*>* args = expr->arguments();
3865 DCHECK(args->length() == 1);
3868 __ AssertString(
eax);
3877 void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) {
3878 Label bailout, done, one_char_separator, long_separator,
3879 non_trivial_array, not_size_one_array, loop,
3880 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
3882 ZoneList<Expression*>* args = expr->arguments();
3883 DCHECK(args->length() == 2);
3889 Register array =
eax;
3890 Register elements =
no_reg;
3892 Register index =
edx;
3894 Register string_length =
ecx;
3896 Register
string =
esi;
3898 Register scratch =
ebx;
3900 Register array_length =
edi;
3901 Register result_pos =
no_reg;
3906 Operand array_length_operand = Operand(
esp, 0);
3910 __ JumpIfSmi(array, &bailout);
3915 __ CheckFastElements(scratch, &bailout);
3919 __ SmiUntag(array_length);
3921 __ mov(result_operand, isolate()->factory()->empty_string());
3925 __ bind(&non_trivial_array);
3926 __ mov(array_length_operand, array_length);
3937 __ Move(index, Immediate(0));
3938 __ Move(string_length, Immediate(0));
3943 __ cmp(index, array_length);
3944 __ Assert(
less, kNoEmptyArraysHereInEmitFastOneByteArrayJoin);
3951 __ JumpIfSmi(
string, &bailout);
3954 __ and_(scratch, Immediate(
3958 __ add(string_length,
3961 __ add(index, Immediate(1));
3962 __ cmp(index, array_length);
3966 __ cmp(array_length, 1);
3969 __ mov(result_operand, scratch);
3972 __ bind(¬_size_one_array);
3975 result_pos = array_length;
3983 __ mov(
string, separator_operand);
3984 __ JumpIfSmi(
string, &bailout);
3987 __ and_(scratch, Immediate(
3994 __ mov(scratch, separator_operand);
3996 __ sub(string_length, scratch);
3997 __ imul(scratch, array_length_operand);
3999 __ add(string_length, scratch);
4002 __ shr(string_length, 1);
4006 __ AllocateOneByteString(result_pos, string_length, scratch, index,
string,
4008 __ mov(result_operand, result_pos);
4012 __ mov(
string, separator_operand);
4015 __ j(
equal, &one_char_separator);
4020 __ mov(index, Immediate(0));
4021 __ jmp(&loop_1_condition);
4034 __ mov(string_length,
4036 __ shr(string_length, 1);
4039 __ CopyBytes(
string, result_pos, string_length, scratch);
4040 __ add(index, Immediate(1));
4041 __ bind(&loop_1_condition);
4042 __ cmp(index, array_length_operand);
4049 __ bind(&one_char_separator);
4052 __ mov_b(separator_operand, scratch);
4054 __ Move(index, Immediate(0));
4057 __ jmp(&loop_2_entry);
4066 __ mov_b(scratch, separator_operand);
4067 __ mov_b(Operand(result_pos, 0), scratch);
4070 __ bind(&loop_2_entry);
4075 __ mov(string_length,
4077 __ shr(string_length, 1);
4080 __ CopyBytes(
string, result_pos, string_length, scratch);
4081 __ add(index, Immediate(1));
4083 __ cmp(index, array_length_operand);
4089 __ bind(&long_separator);
4091 __ Move(index, Immediate(0));
4094 __ jmp(&loop_3_entry);
4103 __ mov(
string, separator_operand);
4104 __ mov(string_length,
4106 __ shr(string_length, 1);
4109 __ CopyBytes(
string, result_pos, string_length, scratch);
4111 __ bind(&loop_3_entry);
4116 __ mov(string_length,
4118 __ shr(string_length, 1);
4121 __ CopyBytes(
string, result_pos, string_length, scratch);
4122 __ add(index, Immediate(1));
4124 __ cmp(index, array_length_operand);
4130 __ mov(result_operand, isolate()->factory()->undefined_value());
4132 __ mov(
eax, result_operand);
4141 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
4142 DCHECK(expr->arguments()->length() == 0);
4143 ExternalReference debug_is_active =
4144 ExternalReference::debug_is_active_address(isolate());
4145 __ movzx_b(
eax, Operand::StaticVariable(debug_is_active));
4151 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4152 if (expr->function() !=
NULL &&
4154 Comment cmnt(
masm_,
"[ InlineRuntimeCall");
4159 Comment cmnt(
masm_,
"[ CallRuntime");
4160 ZoneList<Expression*>* args = expr->arguments();
4162 if (expr->is_jsruntime()) {
4170 if (FLAG_vector_ics) {
4172 Immediate(
Smi::FromInt(expr->CallRuntimeFeedbackSlot())));
4179 __ push(Operand(
esp, 0));
4183 ZoneList<Expression*>* args = expr->arguments();
4184 int arg_count = args->length();
4185 for (
int i = 0;
i < arg_count;
i++) {
4200 int arg_count = args->length();
4201 for (
int i = 0;
i < arg_count;
i++) {
4206 __ CallRuntime(expr->function(), arg_count);
4213 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4214 switch (expr->op()) {
4215 case Token::DELETE: {
4216 Comment cmnt(
masm_,
"[ UnaryOperation (DELETE)");
4217 Property*
property = expr->expression()->AsProperty();
4218 VariableProxy* proxy = expr->expression()->AsVariableProxy();
4220 if (property !=
NULL) {
4226 }
else if (proxy !=
NULL) {
4227 Variable* var = proxy->var();
4231 if (var->IsUnallocated()) {
4233 __ push(Immediate(var->name()));
4237 }
else if (var->IsStackAllocated() || var->IsContextSlot()) {
4241 context()->Plug(var->is_this());
4246 __ push(Immediate(var->name()));
4247 __ CallRuntime(Runtime::kDeleteLookupSlot, 2);
4260 Comment cmnt(
masm_,
"[ UnaryOperation (VOID)");
4262 context()->Plug(isolate()->factory()->undefined_value());
4267 Comment cmnt(
masm_,
"[ UnaryOperation (NOT)");
4272 }
else if (
context()->IsTest()) {
4276 test->false_label(),
4278 test->fall_through());
4279 context()->Plug(test->true_label(), test->false_label());
4286 Label materialize_true, materialize_false, done;
4291 __ bind(&materialize_true);
4293 if (
context()->IsAccumulatorValue()) {
4294 __ mov(
eax, isolate()->factory()->true_value());
4296 __ Push(isolate()->factory()->true_value());
4298 __ jmp(&done, Label::kNear);
4299 __ bind(&materialize_false);
4301 if (
context()->IsAccumulatorValue()) {
4302 __ mov(
eax, isolate()->factory()->false_value());
4304 __ Push(isolate()->factory()->false_value());
4311 case Token::TYPEOF: {
4312 Comment cmnt(
masm_,
"[ UnaryOperation (TYPEOF)");
4313 { StackValueContext
context(
this);
4316 __ CallRuntime(Runtime::kTypeof, 1);
4327 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
4328 DCHECK(expr->expression()->IsValidReferenceExpression());
4330 Comment cmnt(
masm_,
"[ CountOperation");
4337 Property* prop = expr->expression()->AsProperty();
4343 if (prop->IsSuperAccess()) {
4345 VisitSuperReference(prop->obj()->AsSuperReference());
4352 DCHECK(expr->expression()->AsVariableProxy()->var() !=
NULL);
4353 AccumulatorValueContext
context(
this);
4357 if (expr->is_postfix() && !
context()->IsEffect()) {
4384 Label done, stub_call;
4385 JumpPatchSite patch_site(
masm_);
4388 patch_site.EmitJumpIfNotSmi(
eax, &slow, Label::kNear);
4391 if (expr->is_postfix()) {
4396 switch (assign_type) {
4410 if (expr->op() == Token::INC) {
4417 if (expr->op() == Token::INC) {
4422 __ jmp(&stub_call, Label::kNear);
4425 ToNumberStub convert_stub(isolate());
4426 __ CallStub(&convert_stub);
4429 if (expr->is_postfix()) {
4434 switch (assign_type) {
4452 __ bind(&stub_call);
4455 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), expr->binary_op(),
4457 CallIC(code, expr->CountBinOpFeedbackId());
4458 patch_site.EmitPatchInfo();
4462 switch (assign_type) {
4464 if (expr->is_postfix()) {
4466 { EffectContext
context(
this);
4487 prop->key()->AsLiteral()->value());
4491 if (expr->is_postfix()) {
4504 CodeFactory::KeyedStoreIC(isolate(),
strict_mode()).code();
4505 CallIC(ic, expr->CountStoreFeedbackId());
4507 if (expr->is_postfix()) {
4522 VariableProxy* proxy = expr->AsVariableProxy();
4526 if (proxy !=
NULL && proxy->var()->IsUnallocated()) {
4527 Comment cmnt(
masm_,
"[ Global variable");
4530 if (FLAG_vector_ics) {
4532 Immediate(
Smi::FromInt(proxy->VariableFeedbackSlot())));
4539 }
else if (proxy !=
NULL && proxy->var()->IsLookupSlot()) {
4540 Comment cmnt(
masm_,
"[ Lookup slot");
4549 __ push(Immediate(proxy->name()));
4550 __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
4563 Expression* sub_expr,
4564 Handle<String> check) {
4565 Label materialize_true, materialize_false;
4566 Label* if_true =
NULL;
4567 Label* if_false =
NULL;
4568 Label* fall_through =
NULL;
4569 context()->PrepareTest(&materialize_true, &materialize_false,
4570 &if_true, &if_false, &fall_through);
4572 { AccumulatorValueContext
context(
this);
4577 Factory* factory = isolate()->factory();
4579 __ JumpIfSmi(
eax, if_true);
4581 isolate()->factory()->heap_number_map());
4582 Split(
equal, if_true, if_false, fall_through);
4584 __ JumpIfSmi(
eax, if_false);
4590 Split(
zero, if_true, if_false, fall_through);
4592 __ JumpIfSmi(
eax, if_false);
4594 Split(
equal, if_true, if_false, fall_through);
4596 __ cmp(
eax, isolate()->factory()->true_value());
4598 __ cmp(
eax, isolate()->factory()->false_value());
4599 Split(
equal, if_true, if_false, fall_through);
4601 __ cmp(
eax, isolate()->factory()->undefined_value());
4603 __ JumpIfSmi(
eax, if_false);
4610 __ JumpIfSmi(
eax, if_false);
4615 Split(
equal, if_true, if_false, fall_through);
4617 __ JumpIfSmi(
eax, if_false);
4618 __ cmp(
eax, isolate()->factory()->null_value());
4627 Split(
zero, if_true, if_false, fall_through);
4629 if (if_false != fall_through)
__ jmp(if_false);
4631 context()->Plug(if_true, if_false);
4635 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4636 Comment cmnt(
masm_,
"[ CompareOperation");
4645 Label materialize_true, materialize_false;
4646 Label* if_true =
NULL;
4647 Label* if_false =
NULL;
4648 Label* fall_through =
NULL;
4649 context()->PrepareTest(&materialize_true, &materialize_false,
4650 &if_true, &if_false, &fall_through);
4659 __ cmp(
eax, isolate()->factory()->true_value());
4660 Split(
equal, if_true, if_false, fall_through);
4663 case Token::INSTANCEOF: {
4670 Split(
zero, if_true, if_false, fall_through);
4680 JumpPatchSite patch_site(
masm_);
4681 if (inline_smi_code) {
4685 patch_site.EmitJumpIfNotSmi(
ecx, &slow_case, Label::kNear);
4688 __ bind(&slow_case);
4693 Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
4694 CallIC(ic, expr->CompareOperationFeedbackId());
4695 patch_site.EmitPatchInfo();
4699 Split(
cc, if_true, if_false, fall_through);
4705 context()->Plug(if_true, if_false);
4710 Expression* sub_expr,
4712 Label materialize_true, materialize_false;
4713 Label* if_true =
NULL;
4714 Label* if_false =
NULL;
4715 Label* fall_through =
NULL;
4716 context()->PrepareTest(&materialize_true, &materialize_false,
4717 &if_true, &if_false, &fall_through);
4723 ? isolate()->factory()->null_value()
4724 : isolate()->factory()->undefined_value();
4725 if (expr->op() == Token::EQ_STRICT) {
4726 __ cmp(
eax, nil_value);
4727 Split(
equal, if_true, if_false, fall_through);
4730 CallIC(ic, expr->CompareOperationFeedbackId());
4734 context()->Plug(if_true, if_false);
4738 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4756 __ mov(Operand(
ebp, frame_offset), value);
4767 if (declaration_scope->is_global_scope() ||
4768 declaration_scope->is_module_scope()) {
4774 }
else if (declaration_scope->is_eval_scope()) {
4780 DCHECK(declaration_scope->is_function_scope());
4803 ExternalReference pending_message_obj =
4804 ExternalReference::address_of_pending_message_obj(isolate());
4805 __ mov(
edx, Operand::StaticVariable(pending_message_obj));
4808 ExternalReference has_pending_message =
4809 ExternalReference::address_of_has_pending_message(isolate());
4810 __ mov(
edx, Operand::StaticVariable(has_pending_message));
4814 ExternalReference pending_message_script =
4815 ExternalReference::address_of_pending_message_script(isolate());
4816 __ mov(
edx, Operand::StaticVariable(pending_message_script));
4825 ExternalReference pending_message_script =
4826 ExternalReference::address_of_pending_message_script(isolate());
4827 __ mov(Operand::StaticVariable(pending_message_script),
edx);
4831 ExternalReference has_pending_message =
4832 ExternalReference::address_of_has_pending_message(isolate());
4833 __ mov(Operand::StaticVariable(has_pending_message),
edx);
4836 ExternalReference pending_message_obj =
4837 ExternalReference::address_of_pending_message_obj(isolate());
4838 __ mov(Operand::StaticVariable(pending_message_obj),
edx);
4853 #define __ ACCESS_MASM(masm())
4857 int* context_length) {
4864 __ Drop(*stack_depth);
4865 if (*context_length > 0) {
4871 __ call(finally_entry_);
4874 *context_length = 0;
4881 static const byte kJnsInstruction = 0x79;
4882 static const byte kJnsOffset = 0x11;
4883 static const byte kNopByteOne = 0x66;
4884 static const byte kNopByteTwo = 0x90;
4886 static const byte kCallInstruction = 0xe8;
4892 BackEdgeState target_state,
4893 Code* replacement_code) {
4895 Address jns_instr_address = call_target_address - 3;
4896 Address jns_offset_address = call_target_address - 2;
4898 switch (target_state) {
4904 *jns_instr_address = kJnsInstruction;
4905 *jns_offset_address = kJnsOffset;
4907 case ON_STACK_REPLACEMENT:
4908 case OSR_AFTER_STACK_CHECK:
4914 *jns_instr_address = kNopByteOne;
4915 *jns_offset_address = kNopByteTwo;
4921 replacement_code->entry());
4922 unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
4923 unoptimized_code, call_target_address, replacement_code);
4929 Code* unoptimized_code,
4932 Address jns_instr_address = call_target_address - 3;
4933 DCHECK_EQ(kCallInstruction, *(call_target_address - 1));
4935 if (*jns_instr_address == kJnsInstruction) {
4936 DCHECK_EQ(kJnsOffset, *(call_target_address - 2));
4937 DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(),
4943 DCHECK_EQ(kNopByteOne, *jns_instr_address);
4944 DCHECK_EQ(kNopByteTwo, *(call_target_address - 2));
4947 isolate->builtins()->OnStackReplacement()->entry()) {
4948 return ON_STACK_REPLACEMENT;
4951 DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4954 return OSR_AFTER_STACK_CHECK;
static const int kLengthOffset
Isolate * isolate() const
static Address target_address_at(Address pc, ConstantPoolArray *constant_pool)
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 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()
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 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 POINTER_SIZE_ALIGN(value)
#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
static LifetimePosition Min(LifetimePosition a, LifetimePosition b)
bool IsDeclaredVariableMode(VariableMode mode)
const uint32_t kTwoByteStringTag
Operand FieldOperand(Register object, int offset)
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
OStream & dec(OStream &os)
Operand FixedArrayElementOperand(Register array, Register index_as_smi, int additional_offset=0)
kFeedbackVectorOffset flag
MemOperand GlobalObjectOperand()
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
const intptr_t kSmiTagMask
@ RECORD_CONSTRUCTOR_TARGET
const uint32_t kIsNotStringMask
void CopyBytes(uint8_t *target, uint8_t *source)
bool IsFastObjectElementsKind(ElementsKind kind)
Debugger support for the V8 JavaScript engine.