7 #if V8_TARGET_ARCH_MIPS64
34 #define __ ACCESS_MASM(masm_)
47 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
49 info_emitted_ =
false;
54 DCHECK(patch_site_.is_bound() == info_emitted_);
59 void EmitJumpIfNotSmi(Register reg, Label* target) {
60 DCHECK(!patch_site_.is_bound() && !info_emitted_);
62 __ bind(&patch_site_);
65 __ BranchShort(target,
eq, at, Operand(zero_reg));
70 void EmitJumpIfSmi(Register reg, Label* target) {
72 DCHECK(!patch_site_.is_bound() && !info_emitted_);
73 __ bind(&patch_site_);
76 __ BranchShort(target,
ne, at, Operand(zero_reg));
79 void EmitPatchInfo() {
80 if (patch_site_.is_bound()) {
81 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
83 __ andi(zero_reg, reg, delta_to_patch_site %
kImm16Mask);
93 MacroAssembler* masm_;
116 CompilationInfo* info =
info_;
118 isolate()->factory()->NewFixedArray(
function()->handler_count(),
TENURED);
121 Handle<Smi>(
Smi::FromInt(FLAG_interrupt_budget), isolate()));
123 Comment cmnt(
masm_,
"[ function compiled by full code generator");
128 if (strlen(FLAG_stop_at) > 0 &&
129 info->function()->name()->IsUtf8EqualTo(
CStrVector(FLAG_stop_at))) {
137 if (info->strict_mode() ==
SLOPPY && !info->is_native()) {
139 int receiver_offset = info->scope()->num_parameters() *
kPointerSize;
141 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
142 __ Branch(&ok,
ne, a2, Operand(at));
153 FrameScope frame_scope(
masm_, StackFrame::MANUAL);
155 __ Prologue(info->IsCodePreAgingActive());
158 { Comment cmnt(
masm_,
"[ Allocate locals");
159 int locals_count = info->scope()->num_stack_slots();
161 DCHECK(!info->function()->is_generator() || locals_count == 0);
162 if (locals_count > 0) {
163 if (locals_count >= 128) {
166 __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
167 __ Branch(&ok,
hs, t1, Operand(a2));
171 __ LoadRoot(t1, Heap::kUndefinedValueRootIndex);
172 int kMaxPushes = FLAG_optimize_for_size ? 4 : 32;
173 if (locals_count >= kMaxPushes) {
174 int loop_iterations = locals_count / kMaxPushes;
175 __ li(a2, Operand(loop_iterations));
177 __ bind(&loop_header);
180 for (
int i = 0;
i < kMaxPushes;
i++) {
184 __ Dsubu(a2, a2, Operand(1));
185 __ Branch(&loop_header,
ne, a2, Operand(zero_reg));
187 int remaining = locals_count % kMaxPushes;
190 for (
int i = 0;
i < remaining;
i++) {
196 bool function_in_register =
true;
200 if (heap_slots > 0) {
201 Comment cmnt(
masm_,
"[ Allocate context");
203 bool need_write_barrier =
true;
204 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
206 __ Push(info->scope()->GetScopeInfo());
207 __ CallRuntime(Runtime::kNewGlobalContext, 2);
208 }
else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
209 FastNewContextStub stub(isolate(), heap_slots);
212 need_write_barrier =
false;
215 __ CallRuntime(Runtime::kNewFunctionContext, 1);
217 function_in_register =
false;
223 int num_parameters = info->scope()->num_parameters();
224 for (
int i = 0;
i < num_parameters;
i++) {
226 if (var->IsContextSlot()) {
236 if (need_write_barrier) {
237 __ RecordWriteContextSlot(
239 }
else if (FLAG_debug_code) {
241 __ JumpIfInNewSpace(
cp, a0, &done);
242 __ Abort(kExpectedNewSpaceObject);
249 if (arguments !=
NULL) {
251 Comment cmnt(
masm_,
"[ Allocate arguments object");
252 if (!function_in_register) {
259 int num_parameters = info->scope()->num_parameters();
278 ArgumentsAccessStub stub(isolate(), type);
281 SetVar(arguments, v0, a1, a2);
285 __ CallRuntime(Runtime::kTraceEnter, 0);
289 if (
scope()->HasIllegalRedeclaration()) {
290 Comment cmnt(
masm_,
"[ Declarations");
295 { Comment cmnt(
masm_,
"[ Declarations");
298 if (
scope()->is_function_scope() &&
scope()->
function() !=
NULL) {
303 VisitVariableDeclaration(
function);
307 { Comment cmnt(
masm_,
"[ Stack check");
310 __ LoadRoot(at, Heap::kStackLimitRootIndex);
311 __ Branch(&ok,
hs,
sp, Operand(at));
312 Handle<Code> stack_check = isolate()->builtins()->StackCheck();
313 PredictableCodeSizeScope predictable(
masm_,
319 { Comment cmnt(
masm_,
"[ Body");
322 VisitStatements(
function()->body());
330 { Comment cmnt(
masm_,
"[ return <undefined>;");
331 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
339 __ mov(v0, zero_reg);
352 int reset_value = FLAG_interrupt_budget;
355 reset_value = FLAG_interrupt_budget >> 4;
364 Label* back_edge_target) {
371 Comment cmnt(
masm_,
"[ Back edge bookkeeping");
373 DCHECK(back_edge_target->is_bound());
376 Max(1, distance / kCodeSizeMultiplier));
378 __ slt(at, a3, zero_reg);
379 __ beq(at, zero_reg, &ok);
398 Comment cmnt(
masm_,
"[ Return sequence");
407 __ CallRuntime(Runtime::kTraceExit, 1);
412 weight = FLAG_interrupt_budget / FLAG_self_opt_count;
416 Max(1, distance / kCodeSizeMultiplier));
420 __ Branch(&ok,
ge, a3, Operand(zero_reg));
422 __ Call(isolate()->builtins()->InterruptCheck(),
430 Label check_exit_codesize;
460 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
465 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
471 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
480 codegen()->PrepareForBailoutBeforeSplit(condition(),
false,
NULL,
NULL);
481 codegen()->DoTest(
this);
503 codegen()->PrepareForBailoutBeforeSplit(condition(),
507 if (index == Heap::kUndefinedValueRootIndex ||
508 index == Heap::kNullValueRootIndex ||
509 index == Heap::kFalseValueRootIndex) {
510 if (false_label_ != fall_through_)
__ Branch(false_label_);
511 }
else if (index == Heap::kTrueValueRootIndex) {
512 if (true_label_ != fall_through_)
__ Branch(true_label_);
515 codegen()->DoTest(
this);
525 Handle<Object> lit)
const {
538 codegen()->PrepareForBailoutBeforeSplit(condition(),
542 DCHECK(!lit->IsUndetectableObject());
543 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
544 if (false_label_ != fall_through_)
__ Branch(false_label_);
545 }
else if (lit->IsTrue() || lit->IsJSObject()) {
546 if (true_label_ != fall_through_)
__ Branch(true_label_);
547 }
else if (lit->IsString()) {
548 if (String::cast(*lit)->length() == 0) {
549 if (false_label_ != fall_through_)
__ Branch(false_label_);
551 if (true_label_ != fall_through_)
__ Branch(true_label_);
553 }
else if (lit->IsSmi()) {
554 if (Smi::cast(*lit)->value() == 0) {
555 if (false_label_ != fall_through_)
__ Branch(false_label_);
557 if (true_label_ != fall_through_)
__ Branch(true_label_);
562 codegen()->DoTest(
this);
568 Register reg)
const {
576 Register reg)
const {
584 Register reg)
const {
586 if (count > 1)
__ Drop(count - 1);
592 Register reg)
const {
597 codegen()->PrepareForBailoutBeforeSplit(condition(),
false,
NULL,
NULL);
598 codegen()->DoTest(
this);
603 Label* materialize_false)
const {
604 DCHECK(materialize_true == materialize_false);
605 __ bind(materialize_true);
610 Label* materialize_true,
611 Label* materialize_false)
const {
613 __ bind(materialize_true);
616 __ bind(materialize_false);
623 Label* materialize_true,
624 Label* materialize_false)
const {
626 __ bind(materialize_true);
627 __ LoadRoot(at, Heap::kTrueValueRootIndex);
631 __ bind(materialize_false);
632 __ LoadRoot(at, Heap::kFalseValueRootIndex);
639 Label* materialize_false)
const {
640 DCHECK(materialize_true == true_label_);
641 DCHECK(materialize_false == false_label_);
651 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
658 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
659 __ LoadRoot(at, value_root_index);
665 codegen()->PrepareForBailoutBeforeSplit(condition(),
670 if (true_label_ != fall_through_)
__ Branch(true_label_);
672 if (false_label_ != fall_through_)
__ Branch(false_label_);
680 Label* fall_through) {
683 CallIC(ic, condition->test_id());
684 __ mov(at, zero_reg);
685 Split(
ne, v0, Operand(at), if_true, if_false, fall_through);
694 Label* fall_through) {
695 if (if_false == fall_through) {
696 __ Branch(if_true,
cc, lhs, rhs);
697 }
else if (if_true == fall_through) {
700 __ Branch(if_true,
cc, lhs, rhs);
707 DCHECK(var->IsStackAllocated());
711 if (var->IsParameter()) {
721 DCHECK(var->IsContextSlot() || var->IsStackAllocated());
722 if (var->IsContextSlot()) {
724 __ LoadContext(scratch, context_chain_length);
735 __ ld(dest, location);
743 DCHECK(var->IsContextSlot() || var->IsStackAllocated());
744 DCHECK(!scratch0.is(src));
745 DCHECK(!scratch0.is(scratch1));
746 DCHECK(!scratch1.is(src));
748 __ sd(src, location);
750 if (var->IsContextSlot()) {
751 __ RecordWriteContextSlot(scratch0,
762 bool should_normalize,
771 if (should_normalize)
__ Branch(&skip);
773 if (should_normalize) {
774 __ LoadRoot(a4, Heap::kTrueValueRootIndex);
775 Split(
eq, a0, Operand(a4), if_true, if_false,
NULL);
788 __ LoadRoot(a4, Heap::kWithContextMapRootIndex);
789 __ Check(
ne, kDeclarationInWithContext,
791 __ LoadRoot(a4, Heap::kCatchContextMapRootIndex);
792 __ Check(
ne, kDeclarationInCatchContext,
798 void FullCodeGenerator::VisitVariableDeclaration(
799 VariableDeclaration* declaration) {
803 VariableProxy* proxy = declaration->proxy();
805 Variable* variable = proxy->var();
807 switch (variable->location()) {
809 globals_->Add(variable->name(), zone());
810 globals_->Add(variable->binding_needs_init()
811 ? isolate()->factory()->the_hole_value()
812 : isolate()->factory()->undefined_value(),
819 Comment cmnt(
masm_,
"[ VariableDeclaration");
820 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex);
827 Comment cmnt(
masm_,
"[ VariableDeclaration");
829 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
837 Comment cmnt(
masm_,
"[ VariableDeclaration");
838 __ li(a2, Operand(variable->name()));
849 __ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
853 __ mov(a0, zero_reg);
856 __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
863 void FullCodeGenerator::VisitFunctionDeclaration(
864 FunctionDeclaration* declaration) {
865 VariableProxy* proxy = declaration->proxy();
866 Variable* variable = proxy->var();
867 switch (variable->location()) {
869 globals_->Add(variable->name(), zone());
870 Handle<SharedFunctionInfo>
function =
873 if (
function.is_null())
return SetStackOverflow();
880 Comment cmnt(
masm_,
"[ FunctionDeclaration");
887 Comment cmnt(
masm_,
"[ FunctionDeclaration");
893 __ RecordWriteContextSlot(
cp,
906 Comment cmnt(
masm_,
"[ FunctionDeclaration");
907 __ li(a2, Operand(variable->name()));
912 __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
919 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
920 Variable* variable = declaration->proxy()->var();
922 DCHECK(variable->interface()->IsFrozen());
923 Comment cmnt(
masm_,
"[ ModuleDeclaration");
934 __ RecordWriteContextSlot(
cp,
945 Visit(declaration->module());
949 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
950 VariableProxy* proxy = declaration->proxy();
951 Variable* variable = proxy->var();
952 switch (variable->location()) {
958 Comment cmnt(
masm_,
"[ ImportDeclaration");
972 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
983 __ CallRuntime(Runtime::kDeclareGlobals, 3);
991 __ CallRuntime(Runtime::kDeclareModules, 1);
996 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
997 Comment cmnt(
masm_,
"[ SwitchStatement");
998 Breakable nested_statement(
this, stmt);
1005 ZoneList<CaseClause*>* clauses = stmt->cases();
1006 CaseClause* default_clause =
NULL;
1010 for (
int i = 0;
i < clauses->length();
i++) {
1011 CaseClause* clause = clauses->at(
i);
1012 clause->body_target()->Unuse();
1015 if (clause->is_default()) {
1016 default_clause = clause;
1020 Comment cmnt(
masm_,
"[ Case comparison");
1021 __ bind(&next_test);
1031 JumpPatchSite patch_site(
masm_);
1032 if (inline_smi_code) {
1035 patch_site.EmitJumpIfNotSmi(a2, &slow_case);
1037 __ Branch(&next_test,
ne, a1, Operand(a0));
1039 __ Branch(clause->body_target());
1041 __ bind(&slow_case);
1047 CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
1048 CallIC(ic, clause->CompareId());
1049 patch_site.EmitPatchInfo();
1054 __ LoadRoot(at, Heap::kTrueValueRootIndex);
1055 __ Branch(&next_test,
ne, v0, Operand(at));
1057 __ Branch(clause->body_target());
1060 __ Branch(&next_test,
ne, v0, Operand(zero_reg));
1062 __ Branch(clause->body_target());
1067 __ bind(&next_test);
1069 if (default_clause ==
NULL) {
1070 __ Branch(nested_statement.break_label());
1072 __ Branch(default_clause->body_target());
1076 for (
int i = 0;
i < clauses->length();
i++) {
1077 Comment cmnt(
masm_,
"[ Case body");
1078 CaseClause* clause = clauses->at(
i);
1079 __ bind(clause->body_target());
1081 VisitStatements(clause->statements());
1084 __ bind(nested_statement.break_label());
1089 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1090 Comment cmnt(
masm_,
"[ ForInStatement");
1091 int slot = stmt->ForInFeedbackSlot();
1095 ForIn loop_statement(
this, stmt);
1102 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
1103 __ Branch(&exit,
eq, a0, Operand(at));
1104 Register null_value = a5;
1105 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
1106 __ Branch(&exit,
eq, a0, Operand(null_value));
1110 Label convert, done_convert;
1111 __ JumpIfSmi(a0, &convert);
1112 __ GetObjectType(a0, a1, a1);
1118 __ bind(&done_convert);
1124 __ GetObjectType(a0, a1, a1);
1131 __ CheckEnumCache(null_value, &call_runtime);
1137 __ Branch(&use_cache);
1140 __ bind(&call_runtime);
1142 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1149 __ LoadRoot(at, Heap::kMetaMapRootIndex);
1150 __ Branch(&fixed_array,
ne, a2, Operand(at));
1153 Label no_descriptors;
1154 __ bind(&use_cache);
1156 __ EnumLength(a1, v0);
1159 __ LoadInstanceDescriptors(v0, a2);
1169 __ bind(&no_descriptors);
1175 __ bind(&fixed_array);
1184 __ GetObjectType(a2, a3, a3);
1187 __ bind(&non_proxy);
1199 __ Branch(loop_statement.break_label(),
hs, a0, Operand(a1));
1205 __ daddu(a4, a2, a4);
1217 __ Branch(&update_each,
eq, a4, Operand(a2));
1222 __ Branch(&update_each,
eq, a2, Operand(zero_reg));
1230 __ Branch(loop_statement.continue_label(),
eq, a3, Operand(zero_reg));
1234 __ bind(&update_each);
1237 { EffectContext
context(
this);
1242 Visit(stmt->body());
1246 __ bind(loop_statement.continue_label());
1255 __ bind(loop_statement.break_label());
1265 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1266 Comment cmnt(
masm_,
"[ ForOfStatement");
1269 Iteration loop_statement(
this, stmt);
1276 __ bind(loop_statement.continue_label());
1282 Label result_not_done;
1284 loop_statement.break_label(),
1287 __ bind(&result_not_done);
1293 Visit(stmt->body());
1298 __ jmp(loop_statement.continue_label());
1302 __ bind(loop_statement.break_label());
1315 if (!FLAG_always_opt &&
1316 !FLAG_prepare_always_opt &&
1318 scope()->is_function_scope() &&
1319 info->num_literals() == 0) {
1320 FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
1321 __ li(a2, Operand(info));
1324 __ li(a0, Operand(info));
1325 __ LoadRoot(a1, pretenure ? Heap::kTrueValueRootIndex
1326 : Heap::kFalseValueRootIndex);
1328 __ CallRuntime(Runtime::kNewClosure, 3);
1334 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
1335 Comment cmnt(
masm_,
"[ VariableProxy");
1341 Comment cnmt(
masm_,
"[ SuperReference ");
1346 Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
1352 __ Branch(&done,
ne, v0, Operand(isolate()->factory()->undefined_value()));
1353 __ CallRuntime(Runtime::kThrowNonMethodError, 0);
1361 Register current =
cp;
1367 if (s->num_heap_slots() > 0) {
1368 if (s->calls_sloppy_eval()) {
1371 __ Branch(slow,
ne, temp, Operand(zero_reg));
1380 if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope())
break;
1381 s = s->outer_scope();
1384 if (s->is_eval_scope()) {
1386 if (!current.is(next)) {
1387 __ Move(next, current);
1392 __ LoadRoot(a4, Heap::kNativeContextMapRootIndex);
1393 __ Branch(&fast,
eq, temp, Operand(a4));
1396 __ Branch(slow,
ne, temp, Operand(zero_reg));
1405 if (FLAG_vector_ics) {
1419 DCHECK(var->IsContextSlot());
1425 if (s->num_heap_slots() > 0) {
1426 if (s->calls_sloppy_eval()) {
1429 __ Branch(slow,
ne, temp, Operand(zero_reg));
1438 __ Branch(slow,
ne, temp, Operand(zero_reg));
1456 Variable* var = proxy->var();
1461 Variable* local = var->local_if_not_shadowed();
1463 if (local->mode() ==
LET || local->mode() ==
CONST ||
1465 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
1466 __ dsubu(at, v0, at);
1468 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
1469 __ Movz(v0, a0, at);
1471 __ Branch(done,
ne, at, Operand(zero_reg));
1472 __ li(a0, Operand(var->name()));
1474 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1485 Variable* var = proxy->var();
1489 switch (var->location()) {
1491 Comment cmnt(
masm_,
"[ Global variable");
1496 if (FLAG_vector_ics) {
1508 Comment cmnt(
masm_, var->IsContextSlot() ?
"[ Context variable"
1509 :
"[ Stack variable");
1510 if (var->binding_needs_init()) {
1534 bool skip_init_check;
1535 if (var->scope()->DeclarationScope() !=
scope()->DeclarationScope()) {
1536 skip_init_check =
false;
1542 var->initializer_position() < proxy->position();
1545 if (!skip_init_check) {
1548 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
1549 __ dsubu(at, v0, at);
1550 if (var->mode() ==
LET || var->mode() ==
CONST) {
1554 __ Branch(&done,
ne, at, Operand(zero_reg));
1555 __ li(a0, Operand(var->name()));
1557 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1562 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
1563 __ Movz(v0, a0, at);
1574 Comment cmnt(
masm_,
"[ Lookup variable");
1580 __ li(a1, Operand(var->name()));
1582 __ CallRuntime(Runtime::kLoadLookupSlot, 2);
1590 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1591 Comment cmnt(
masm_,
"[ RegExpLiteral");
1602 int literal_offset =
1605 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
1606 __ Branch(&materialized,
ne, a5, Operand(at));
1611 __ li(a2, Operand(expr->pattern()));
1612 __ li(a1, Operand(expr->flags()));
1614 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1617 __ bind(&materialized);
1619 Label allocated, runtime_allocate;
1623 __ bind(&runtime_allocate);
1626 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1629 __ bind(&allocated);
1641 if (expression ==
NULL) {
1642 __ LoadRoot(a1, Heap::kNullValueRootIndex);
1650 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1651 Comment cmnt(
masm_,
"[ ObjectLiteral");
1653 expr->BuildConstantProperties(isolate());
1654 Handle<FixedArray> constant_properties = expr->constant_properties();
1658 __ li(a1, Operand(constant_properties));
1659 int flags = expr->fast_elements()
1660 ? ObjectLiteral::kFastElements
1661 : ObjectLiteral::kNoFlags;
1662 flags |= expr->has_function()
1663 ? ObjectLiteral::kHasFunction
1664 : ObjectLiteral::kNoFlags;
1666 int properties_count = constant_properties->length() / 2;
1667 if (expr->may_store_doubles() || expr->depth() > 1 ||
1668 masm()->serializer_enabled() ||
flags != ObjectLiteral::kFastElements ||
1671 __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
1673 FastCloneShallowObjectStub stub(isolate(), properties_count);
1679 bool result_saved =
false;
1684 expr->CalculateEmitStore(zone());
1686 AccessorTable accessor_table(zone());
1687 for (
int i = 0;
i < expr->properties()->length();
i++) {
1688 ObjectLiteral::Property*
property = expr->properties()->at(
i);
1689 if (property->IsCompileTimeValue())
continue;
1691 Literal* key =
property->key();
1692 Expression* value =
property->value();
1693 if (!result_saved) {
1695 result_saved =
true;
1697 switch (property->kind()) {
1700 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1703 case ObjectLiteral::Property::COMPUTED:
1704 if (key->value()->IsInternalizedString()) {
1705 if (property->emit_store()) {
1723 if (property->emit_store()) {
1726 __ CallRuntime(Runtime::kSetProperty, 4);
1731 case ObjectLiteral::Property::PROTOTYPE:
1736 if (property->emit_store()) {
1737 __ CallRuntime(Runtime::kSetPrototype, 2);
1742 case ObjectLiteral::Property::GETTER:
1743 accessor_table.lookup(key)->second->getter = value;
1745 case ObjectLiteral::Property::SETTER:
1746 accessor_table.lookup(key)->second->setter = value;
1753 for (AccessorTable::Iterator it = accessor_table.begin();
1754 it != accessor_table.end();
1763 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
1766 if (expr->has_function()) {
1770 __ CallRuntime(Runtime::kToFastProperties, 1);
1781 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1782 Comment cmnt(
masm_,
"[ ArrayLiteral");
1784 expr->BuildConstantElements(isolate());
1785 int flags = expr->depth() == 1
1786 ? ArrayLiteral::kShallowElements
1787 : ArrayLiteral::kNoFlags;
1789 ZoneList<Expression*>* subexprs = expr->values();
1790 int length = subexprs->length();
1792 Handle<FixedArray> constant_elements = expr->constant_elements();
1793 DCHECK_EQ(2, constant_elements->length());
1795 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1796 bool has_fast_elements =
1798 Handle<FixedArrayBase> constant_elements_values(
1799 FixedArrayBase::cast(constant_elements->get(1)));
1802 if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
1812 __ li(a1, Operand(constant_elements));
1816 __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
1818 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1822 bool result_saved =
false;
1826 for (
int i = 0;
i < length;
i++) {
1827 Expression* subexpr = subexprs->at(
i);
1832 if (!result_saved) {
1835 result_saved =
true;
1852 StoreArrayLiteralElementStub stub(isolate());
1867 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1868 DCHECK(expr->target()->IsValidReferenceExpression());
1870 Comment cmnt(
masm_,
"[ Assignment");
1876 Property*
property = expr->target()->AsProperty();
1877 if (property !=
NULL) {
1878 assign_type = (
property->key()->IsPropertyName())
1884 switch (assign_type) {
1889 if (expr->is_compound()) {
1899 if (expr->is_compound()) {
1914 if (expr->is_compound()) {
1915 { AccumulatorValueContext
context(
this);
1916 switch (assign_type) {
1940 AccumulatorValueContext
context(
this);
1961 switch (assign_type) {
1978 void FullCodeGenerator::VisitYield(Yield* expr) {
1979 Comment cmnt(
masm_,
"[ Yield");
1984 switch (expr->yield_kind()) {
1985 case Yield::kSuspend:
1990 case Yield::kInitial: {
1991 Label suspend, continuation, post_runtime, resume;
1995 __ bind(&continuation);
2008 __ Branch(&post_runtime,
eq,
sp, Operand(a1));
2010 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2012 __ bind(&post_runtime);
2021 case Yield::kFinal: {
2033 case Yield::kDelegating: {
2040 Label l_catch, l_try, l_suspend, l_continuation, l_resume;
2041 Label l_next, l_call;
2045 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
2052 __ LoadRoot(a2, Heap::kthrow_stringRootIndex);
2062 __ PushTryHandler(StackHandler::CATCH, expr->index());
2066 __ bind(&l_continuation);
2069 __ bind(&l_suspend);
2070 const int generator_object_depth =
kPointerSize + handler_size;
2080 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2090 __ LoadRoot(load_name, Heap::knext_stringRootIndex);
2092 __ Push(load_name, a3, a0);
2098 if (FLAG_vector_ics) {
2102 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
2114 __ Move(load_receiver, v0);
2116 __ push(load_receiver);
2117 __ LoadRoot(load_name, Heap::kdone_stringRootIndex);
2118 if (FLAG_vector_ics) {
2126 __ Branch(&l_try,
eq, v0, Operand(zero_reg));
2129 __ pop(load_receiver);
2130 __ LoadRoot(load_name, Heap::kvalue_stringRootIndex);
2131 if (FLAG_vector_ics) {
2136 context()->DropAndPlug(2, v0);
2155 Label wrong_state, closed_state, done;
2159 __ Branch(&closed_state,
eq, a3, Operand(zero_reg));
2160 __ Branch(&wrong_state,
lt, a3, Operand(zero_reg));
2176 __ LoadRoot(a2, Heap::kTheHoleValueRootIndex);
2177 Label push_argument_holes, push_frame;
2178 __ bind(&push_argument_holes);
2179 __ Dsubu(a3, a3, Operand(1));
2180 __ Branch(&push_frame,
lt, a3, Operand(zero_reg));
2182 __ jmp(&push_argument_holes);
2187 __ bind(&push_frame);
2188 __ Call(&resume_frame);
2190 __ bind(&resume_frame);
2208 __ Branch(&slow_resume,
ne, a3, Operand(zero_reg));
2212 __ Daddu(a3, a3, Operand(a2));
2216 __ bind(&slow_resume);
2221 Label push_operand_holes, call_resume;
2222 __ bind(&push_operand_holes);
2223 __ Dsubu(a3, a3, Operand(1));
2224 __ Branch(&call_resume,
lt, a3, Operand(zero_reg));
2226 __ Branch(&push_operand_holes);
2227 __ bind(&call_resume);
2231 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
2233 __ stop(
"not-reached");
2236 __ bind(&closed_state);
2239 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
2246 __ CallRuntime(Runtime::kThrow, 1);
2251 __ bind(&wrong_state);
2253 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
2264 Handle<Map>
map(isolate()->native_context()->iterator_result_map());
2266 __ Allocate(
map->instance_size(), v0, a2, a3, &gc_required,
TAG_OBJECT);
2269 __ bind(&gc_required);
2271 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2275 __ bind(&allocated);
2276 __ li(a1, Operand(
map));
2278 __ li(a3, Operand(isolate()->factory()->ToBoolean(done)));
2279 __ li(a4, Operand(isolate()->factory()->empty_fixed_array()));
2298 Literal* key = prop->key()->AsLiteral();
2299 DCHECK(!prop->IsSuperAccess());
2302 if (FLAG_vector_ics) {
2314 Literal* key = prop->key()->AsLiteral();
2315 DCHECK(!key->value()->IsSmi());
2316 DCHECK(prop->IsSuperAccess());
2318 SuperReference* super_ref = prop->obj()->AsSuperReference();
2323 __ CallRuntime(Runtime::kLoadFromSuper, 3);
2330 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
2331 if (FLAG_vector_ics) {
2336 CallIC(ic, prop->PropertyFeedbackId());
2344 Expression* left_expr,
2345 Expression* right_expr) {
2346 Label done, smi_case, stub_call;
2348 Register scratch1 = a2;
2349 Register scratch2 = a3;
2353 Register right = a0;
2358 __ Or(scratch1, left, Operand(right));
2360 JumpPatchSite patch_site(
masm_);
2361 patch_site.EmitJumpIfSmi(scratch1, &smi_case);
2363 __ bind(&stub_call);
2364 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op,
mode).code();
2365 CallIC(code, expr->BinaryOperationFeedbackId());
2366 patch_site.EmitPatchInfo();
2374 __ GetLeastBitsFromSmi(scratch1, right, 5);
2375 __ dsrav(right, left, scratch1);
2376 __ And(v0, right, Operand(0xffffffff00000000L));
2379 __ SmiUntag(scratch1, left);
2380 __ GetLeastBitsFromSmi(scratch2, right, 5);
2381 __ dsllv(scratch1, scratch1, scratch2);
2382 __ SmiTag(v0, scratch1);
2386 __ SmiUntag(scratch1, left);
2387 __ GetLeastBitsFromSmi(scratch2, right, 5);
2388 __ dsrlv(scratch1, scratch1, scratch2);
2389 __ And(scratch2, scratch1, 0x80000000);
2390 __ Branch(&stub_call,
ne, scratch2, Operand(zero_reg));
2391 __ SmiTag(v0, scratch1);
2395 __ AdduAndCheckForOverflow(v0, left, right, scratch1);
2396 __ BranchOnOverflow(&stub_call, scratch1);
2399 __ SubuAndCheckForOverflow(v0, left, right, scratch1);
2400 __ BranchOnOverflow(&stub_call, scratch1);
2403 __ Dmulh(v0, left, right);
2404 __ dsra32(scratch2, v0, 0);
2405 __ sra(scratch1, v0, 31);
2409 __ Daddu(scratch2, right, left);
2410 __ Branch(&stub_call,
lt, scratch2, Operand(zero_reg));
2412 __ mov(v0, zero_reg);
2416 __ Or(v0, left, Operand(right));
2418 case Token::BIT_AND:
2419 __ And(v0, left, Operand(right));
2421 case Token::BIT_XOR:
2422 __ Xor(v0, left, Operand(right));
2438 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op,
mode).code();
2439 JumpPatchSite patch_site(
masm_);
2440 CallIC(code, expr->BinaryOperationFeedbackId());
2441 patch_site.EmitPatchInfo();
2447 DCHECK(expr->IsValidReferenceExpression());
2453 Property* prop = expr->AsProperty();
2455 assign_type = (prop->key()->IsPropertyName())
2460 switch (assign_type) {
2462 Variable* var = expr->AsVariableProxy()->var();
2473 Operand(prop->key()->AsLiteral()->value()));
2485 CodeFactory::KeyedStoreIC(isolate(),
strict_mode()).code();
2497 if (var->IsContextSlot()) {
2501 __ RecordWriteContextSlot(
2508 if (var->IsUnallocated()) {
2514 }
else if (op == Token::INIT_CONST_LEGACY) {
2516 DCHECK(!var->IsParameter());
2517 if (var->IsLookupSlot()) {
2518 __ li(a0, Operand(var->name()));
2520 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3);
2522 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2525 __ ld(a2, location);
2526 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2527 __ Branch(&skip,
ne, a2, Operand(at));
2532 }
else if (var->mode() ==
LET && op != Token::INIT_LET) {
2534 DCHECK(!var->IsLookupSlot());
2535 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2538 __ ld(a3, location);
2539 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex);
2540 __ Branch(&assign,
ne, a3, Operand(a4));
2541 __ li(a3, Operand(var->name()));
2543 __ CallRuntime(Runtime::kThrowReferenceError, 1);
2548 }
else if (!var->is_const_mode() || op == Token::INIT_CONST) {
2549 if (var->IsLookupSlot()) {
2551 __ li(a4, Operand(var->name()));
2558 __ CallRuntime(Runtime::kStoreLookupSlot, 4);
2562 DCHECK((var->IsStackAllocated() || var->IsContextSlot()));
2566 __ ld(a2, location);
2567 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex);
2568 __ Check(
eq, kLetBindingReInitialization, a2, Operand(a4));
2579 Property* prop = expr->target()->AsProperty();
2581 DCHECK(prop->key()->IsLiteral());
2587 Operand(prop->key()->AsLiteral()->value()));
2610 Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(),
strict_mode()).code();
2611 CallIC(ic, expr->AssignmentFeedbackId());
2618 void FullCodeGenerator::VisitProperty(Property* expr) {
2619 Comment cmnt(
masm_,
"[ Property");
2620 Expression* key = expr->key();
2622 if (key->IsPropertyName()) {
2623 if (!expr->IsSuperAccess()) {
2644 TypeFeedbackId
id) {
2652 Expression* callee = expr->expression();
2654 CallICState::CallType call_type =
2655 callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD;
2658 if (call_type == CallICState::FUNCTION) {
2659 { StackValueContext
context(
this);
2665 __ Push(isolate()->factory()->undefined_value());
2668 DCHECK(callee->IsProperty());
2669 DCHECK(!callee->AsProperty()->IsSuperAccess());
2684 Expression* callee = expr->expression();
2685 DCHECK(callee->IsProperty());
2686 Property* prop = callee->AsProperty();
2687 DCHECK(prop->IsSuperAccess());
2690 Literal* key = prop->key()->AsLiteral();
2691 DCHECK(!key->value()->IsSmi());
2693 const Register scratch = a1;
2694 SuperReference* super_ref = prop->obj()->AsSuperReference();
2709 __ CallRuntime(Runtime::kLoadFromSuper, 3);
2717 EmitCall(expr, CallICState::METHOD);
2727 Expression* callee = expr->expression();
2730 DCHECK(callee->IsProperty());
2741 EmitCall(expr, CallICState::METHOD);
2747 ZoneList<Expression*>* args = expr->arguments();
2748 int arg_count = args->length();
2749 { PreservePositionScope
scope(
masm()->positions_recorder());
2750 for (
int i = 0;
i < arg_count;
i++) {
2758 isolate(), arg_count, call_type);
2767 context()->DropAndPlug(1, v0);
2773 if (arg_count > 0) {
2776 __ LoadRoot(a6, Heap::kUndefinedValueRootIndex);
2791 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
2795 void FullCodeGenerator::VisitCall(Call* expr) {
2799 expr->return_is_recorded_ =
false;
2802 Comment cmnt(
masm_,
"[ Call");
2803 Expression* callee = expr->expression();
2804 Call::CallType call_type = expr->GetCallType(isolate());
2806 if (call_type == Call::POSSIBLY_EVAL_CALL) {
2811 ZoneList<Expression*>* args = expr->arguments();
2812 int arg_count = args->length();
2814 { PreservePositionScope pos_scope(
masm()->positions_recorder());
2816 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
2820 for (
int i = 0;
i < arg_count;
i++) {
2843 context()->DropAndPlug(1, v0);
2844 }
else if (call_type == Call::GLOBAL_CALL) {
2846 }
else if (call_type == Call::LOOKUP_SLOT_CALL) {
2848 VariableProxy* proxy = callee->AsVariableProxy();
2851 { PreservePositionScope
scope(
masm()->positions_recorder());
2861 __ li(a2, Operand(proxy->name()));
2863 __ CallRuntime(Runtime::kLoadLookupSlot, 2);
2869 if (done.is_linked()) {
2877 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
2885 }
else if (call_type == Call::PROPERTY_CALL) {
2886 Property*
property = callee->AsProperty();
2887 bool is_named_call =
property->key()->IsPropertyName();
2889 if (property->IsSuperAccess() && is_named_call) {
2893 PreservePositionScope
scope(
masm()->positions_recorder());
2896 if (is_named_call) {
2903 DCHECK(call_type == Call::OTHER_CALL);
2905 { PreservePositionScope
scope(
masm()->positions_recorder());
2908 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
2916 DCHECK(expr->return_is_recorded_);
2921 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
2922 Comment cmnt(
masm_,
"[ CallNew");
2933 ZoneList<Expression*>* args = expr->arguments();
2934 int arg_count = args->length();
2935 for (
int i = 0;
i < arg_count;
i++) {
2943 __ li(a0, Operand(arg_count));
2947 if (FLAG_pretenuring_call_new) {
2949 DCHECK(expr->AllocationSiteFeedbackSlot() ==
2950 expr->CallNewFeedbackSlot() + 1);
2963 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2964 ZoneList<Expression*>* args = expr->arguments();
2965 DCHECK(args->length() == 1);
2969 Label materialize_true, materialize_false;
2970 Label* if_true =
NULL;
2971 Label* if_false =
NULL;
2972 Label* fall_through =
NULL;
2973 context()->PrepareTest(&materialize_true, &materialize_false,
2974 &if_true, &if_false, &fall_through);
2978 Split(
eq, a4, Operand(zero_reg), if_true, if_false, fall_through);
2980 context()->Plug(if_true, if_false);
2984 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
2985 ZoneList<Expression*>* args = expr->arguments();
2986 DCHECK(args->length() == 1);
2990 Label materialize_true, materialize_false;
2991 Label* if_true =
NULL;
2992 Label* if_false =
NULL;
2993 Label* fall_through =
NULL;
2994 context()->PrepareTest(&materialize_true, &materialize_false,
2995 &if_true, &if_false, &fall_through);
2998 __ NonNegativeSmiTst(v0, at);
2999 Split(
eq, at, Operand(zero_reg), if_true, if_false, fall_through);
3001 context()->Plug(if_true, if_false);
3005 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
3006 ZoneList<Expression*>* args = expr->arguments();
3007 DCHECK(args->length() == 1);
3011 Label materialize_true, materialize_false;
3012 Label* if_true =
NULL;
3013 Label* if_false =
NULL;
3014 Label* fall_through =
NULL;
3015 context()->PrepareTest(&materialize_true, &materialize_false,
3016 &if_true, &if_false, &fall_through);
3018 __ JumpIfSmi(v0, if_false);
3019 __ LoadRoot(at, Heap::kNullValueRootIndex);
3020 __ Branch(if_true,
eq, v0, Operand(at));
3025 __ Branch(if_false,
ne, at, Operand(zero_reg));
3030 if_true, if_false, fall_through);
3032 context()->Plug(if_true, if_false);
3036 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
3037 ZoneList<Expression*>* args = expr->arguments();
3038 DCHECK(args->length() == 1);
3042 Label materialize_true, materialize_false;
3043 Label* if_true =
NULL;
3044 Label* if_false =
NULL;
3045 Label* fall_through =
NULL;
3046 context()->PrepareTest(&materialize_true, &materialize_false,
3047 &if_true, &if_false, &fall_through);
3049 __ JumpIfSmi(v0, if_false);
3050 __ GetObjectType(v0, a1, a1);
3053 if_true, if_false, fall_through);
3055 context()->Plug(if_true, if_false);
3059 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
3060 ZoneList<Expression*>* args = expr->arguments();
3061 DCHECK(args->length() == 1);
3065 Label materialize_true, materialize_false;
3066 Label* if_true =
NULL;
3067 Label* if_false =
NULL;
3068 Label* fall_through =
NULL;
3069 context()->PrepareTest(&materialize_true, &materialize_false,
3070 &if_true, &if_false, &fall_through);
3072 __ JumpIfSmi(v0, if_false);
3077 Split(
ne, at, Operand(zero_reg), if_true, if_false, fall_through);
3079 context()->Plug(if_true, if_false);
3083 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
3084 CallRuntime* expr) {
3085 ZoneList<Expression*>* args = expr->arguments();
3086 DCHECK(args->length() == 1);
3090 Label materialize_true, materialize_false, skip_lookup;
3091 Label* if_true =
NULL;
3092 Label* if_false =
NULL;
3093 Label* fall_through =
NULL;
3094 context()->PrepareTest(&materialize_true, &materialize_false,
3095 &if_true, &if_false, &fall_through);
3097 __ AssertNotSmi(v0);
3102 __ Branch(&skip_lookup,
ne, a4, Operand(zero_reg));
3107 __ LoadRoot(a4, Heap::kHashTableMapRootIndex);
3108 __ Branch(if_false,
eq, a2, Operand(a4));
3113 Label entry, loop, done;
3116 __ NumberOfOwnDescriptors(a3, a1);
3117 __ Branch(&done,
eq, a3, Operand(zero_reg));
3119 __ LoadInstanceDescriptors(a1, a4);
3127 __ Dmul(a3, a3, at);
3133 __ Daddu(a2, a2, a5);
3139 __ li(a6, Operand(isolate()->factory()->value_of_string()));
3143 __ Branch(if_false,
eq, a3, Operand(a6));
3146 __ Branch(&loop,
ne, a4, Operand(a2));
3155 __ bind(&skip_lookup);
3160 __ JumpIfSmi(a2, if_false);
3166 Split(
eq, a2, Operand(a3), if_true, if_false, fall_through);
3168 context()->Plug(if_true, if_false);
3172 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
3173 ZoneList<Expression*>* args = expr->arguments();
3174 DCHECK(args->length() == 1);
3178 Label materialize_true, materialize_false;
3179 Label* if_true =
NULL;
3180 Label* if_false =
NULL;
3181 Label* fall_through =
NULL;
3182 context()->PrepareTest(&materialize_true, &materialize_false,
3183 &if_true, &if_false, &fall_through);
3185 __ JumpIfSmi(v0, if_false);
3186 __ GetObjectType(v0, a1, a2);
3189 __ Branch(if_false);
3191 context()->Plug(if_true, if_false);
3195 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
3196 ZoneList<Expression*>* args = expr->arguments();
3197 DCHECK(args->length() == 1);
3201 Label materialize_true, materialize_false;
3202 Label* if_true =
NULL;
3203 Label* if_false =
NULL;
3204 Label* fall_through =
NULL;
3205 context()->PrepareTest(&materialize_true, &materialize_false,
3206 &if_true, &if_false, &fall_through);
3208 __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, if_false,
DO_SMI_CHECK);
3211 __ li(a4, 0x80000000);
3213 __ Branch(¬_nan,
ne, a2, Operand(a4));
3214 __ mov(a4, zero_reg);
3219 Split(
eq, a2, Operand(a4), if_true, if_false, fall_through);
3221 context()->Plug(if_true, if_false);
3225 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
3226 ZoneList<Expression*>* args = expr->arguments();
3227 DCHECK(args->length() == 1);
3231 Label materialize_true, materialize_false;
3232 Label* if_true =
NULL;
3233 Label* if_false =
NULL;
3234 Label* fall_through =
NULL;
3235 context()->PrepareTest(&materialize_true, &materialize_false,
3236 &if_true, &if_false, &fall_through);
3238 __ JumpIfSmi(v0, if_false);
3239 __ GetObjectType(v0, a1, a1);
3242 if_true, if_false, fall_through);
3244 context()->Plug(if_true, if_false);
3248 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
3249 ZoneList<Expression*>* args = expr->arguments();
3250 DCHECK(args->length() == 1);
3254 Label materialize_true, materialize_false;
3255 Label* if_true =
NULL;
3256 Label* if_false =
NULL;
3257 Label* fall_through =
NULL;
3258 context()->PrepareTest(&materialize_true, &materialize_false,
3259 &if_true, &if_false, &fall_through);
3261 __ JumpIfSmi(v0, if_false);
3262 __ GetObjectType(v0, a1, a1);
3266 context()->Plug(if_true, if_false);
3270 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
3271 DCHECK(expr->arguments()->length() == 0);
3273 Label materialize_true, materialize_false;
3274 Label* if_true =
NULL;
3275 Label* if_false =
NULL;
3276 Label* fall_through =
NULL;
3277 context()->PrepareTest(&materialize_true, &materialize_false,
3278 &if_true, &if_false, &fall_through);
3284 Label check_frame_marker;
3286 __ Branch(&check_frame_marker,
ne,
3291 __ bind(&check_frame_marker);
3295 if_true, if_false, fall_through);
3297 context()->Plug(if_true, if_false);
3301 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
3302 ZoneList<Expression*>* args = expr->arguments();
3303 DCHECK(args->length() == 2);
3309 Label materialize_true, materialize_false;
3310 Label* if_true =
NULL;
3311 Label* if_false =
NULL;
3312 Label* fall_through =
NULL;
3313 context()->PrepareTest(&materialize_true, &materialize_false,
3314 &if_true, &if_false, &fall_through);
3318 Split(
eq, v0, Operand(a1), if_true, if_false, fall_through);
3320 context()->Plug(if_true, if_false);
3324 void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
3325 ZoneList<Expression*>* args = expr->arguments();
3326 DCHECK(args->length() == 1);
3339 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
3340 DCHECK(expr->arguments()->length() == 0);
3348 __ Branch(&exit,
ne, a3,
3360 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
3361 ZoneList<Expression*>* args = expr->arguments();
3362 DCHECK(args->length() == 1);
3363 Label done,
null,
function, non_function_constructor;
3368 __ JumpIfSmi(v0, &
null);
3375 __ GetObjectType(v0, v0, a1);
3390 __ GetObjectType(v0, a1, a1);
3401 __ LoadRoot(v0, Heap::kFunction_stringRootIndex);
3405 __ bind(&non_function_constructor);
3406 __ LoadRoot(v0, Heap::kObject_stringRootIndex);
3411 __ LoadRoot(v0, Heap::kNullValueRootIndex);
3420 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
3422 SubStringStub stub(isolate());
3423 ZoneList<Expression*>* args = expr->arguments();
3424 DCHECK(args->length() == 3);
3433 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
3435 RegExpExecStub stub(isolate());
3436 ZoneList<Expression*>* args = expr->arguments();
3437 DCHECK(args->length() == 4);
3447 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
3448 ZoneList<Expression*>* args = expr->arguments();
3449 DCHECK(args->length() == 1);
3455 __ JumpIfSmi(v0, &done);
3457 __ GetObjectType(v0, a1, a1);
3467 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
3468 ZoneList<Expression*>* args = expr->arguments();
3469 DCHECK(args->length() == 2);
3471 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value()));
3475 Label runtime, done, not_date_object;
3476 Register
object = v0;
3477 Register result = v0;
3478 Register scratch0 = t1;
3479 Register scratch1 = a1;
3481 __ JumpIfSmi(
object, ¬_date_object);
3482 __ GetObjectType(
object, scratch1, scratch1);
3485 if (index->value() == 0) {
3490 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
3491 __ li(scratch1, Operand(stamp));
3494 __ Branch(&runtime,
ne, scratch1, Operand(scratch0));
3500 __ PrepareCallCFunction(2, scratch1);
3501 __ li(a1, Operand(index));
3502 __ Move(a0,
object);
3503 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3507 __ bind(¬_date_object);
3508 __ CallRuntime(Runtime::kThrowNotDateError, 0);
3514 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
3515 ZoneList<Expression*>* args = expr->arguments();
3518 Register
string = v0;
3519 Register index = a1;
3520 Register value = a2;
3525 __ Pop(index, value);
3527 if (FLAG_debug_code) {
3528 __ SmiTst(value, at);
3529 __ Check(
eq, kNonSmiValue, at, Operand(zero_reg));
3530 __ SmiTst(index, at);
3531 __ Check(
eq, kNonSmiIndex, at, Operand(zero_reg));
3532 __ SmiUntag(index, index);
3534 Register scratch = t1;
3535 __ EmitSeqStringSetCharCheck(
3536 string, index, value, scratch, one_byte_seq_type);
3537 __ SmiTag(index, index);
3540 __ SmiUntag(value, value);
3545 __ Daddu(at, at, index);
3551 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
3552 ZoneList<Expression*>* args = expr->arguments();
3555 Register
string = v0;
3556 Register index = a1;
3557 Register value = a2;
3562 __ Pop(index, value);
3564 if (FLAG_debug_code) {
3565 __ SmiTst(value, at);
3566 __ Check(
eq, kNonSmiValue, at, Operand(zero_reg));
3567 __ SmiTst(index, at);
3568 __ Check(
eq, kNonSmiIndex, at, Operand(zero_reg));
3569 __ SmiUntag(index, index);
3571 Register scratch = t1;
3572 __ EmitSeqStringSetCharCheck(
3573 string, index, value, scratch, two_byte_seq_type);
3574 __ SmiTag(index, index);
3577 __ SmiUntag(value, value);
3581 __ dsra(index, index, 32 - 1);
3582 __ Daddu(at, at, index);
3589 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
3591 ZoneList<Expression*>* args = expr->arguments();
3592 DCHECK(args->length() == 2);
3601 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
3602 ZoneList<Expression*>* args = expr->arguments();
3603 DCHECK(args->length() == 2);
3611 __ JumpIfSmi(a1, &done);
3614 __ GetObjectType(a1, a2, a2);
3622 __ RecordWriteField(
3630 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
3631 ZoneList<Expression*>* args = expr->arguments();
3638 NumberToStringStub stub(isolate());
3644 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
3645 ZoneList<Expression*>* args = expr->arguments();
3646 DCHECK(args->length() == 1);
3651 StringCharFromCodeGenerator generator(v0, a1);
3652 generator.GenerateFast(
masm_);
3655 NopRuntimeCallHelper call_helper;
3656 generator.GenerateSlow(
masm_, call_helper);
3663 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
3664 ZoneList<Expression*>* args = expr->arguments();
3665 DCHECK(args->length() == 2);
3671 Register
object = a1;
3672 Register index = a0;
3673 Register result = v0;
3677 Label need_conversion;
3678 Label index_out_of_range;
3680 StringCharCodeAtGenerator generator(
object,
3685 &index_out_of_range,
3687 generator.GenerateFast(
masm_);
3690 __ bind(&index_out_of_range);
3693 __ LoadRoot(result, Heap::kNanValueRootIndex);
3696 __ bind(&need_conversion);
3699 __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
3702 NopRuntimeCallHelper call_helper;
3703 generator.GenerateSlow(
masm_, call_helper);
3710 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
3711 ZoneList<Expression*>* args = expr->arguments();
3712 DCHECK(args->length() == 2);
3718 Register
object = a1;
3719 Register index = a0;
3720 Register scratch = a3;
3721 Register result = v0;
3725 Label need_conversion;
3726 Label index_out_of_range;
3728 StringCharAtGenerator generator(
object,
3734 &index_out_of_range,
3736 generator.GenerateFast(
masm_);
3739 __ bind(&index_out_of_range);
3742 __ LoadRoot(result, Heap::kempty_stringRootIndex);
3745 __ bind(&need_conversion);
3751 NopRuntimeCallHelper call_helper;
3752 generator.GenerateSlow(
masm_, call_helper);
3759 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3760 ZoneList<Expression*>* args = expr->arguments();
3773 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3774 ZoneList<Expression*>* args = expr->arguments();
3780 StringCompareStub stub(isolate());
3786 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
3787 ZoneList<Expression*>* args = expr->arguments();
3788 DCHECK(args->length() >= 2);
3790 int arg_count = args->length() - 2;
3791 for (
int i = 0;
i < arg_count + 1;
i++) {
3796 Label runtime, done;
3798 __ JumpIfSmi(v0, &runtime);
3799 __ GetObjectType(v0, a1, a1);
3804 ParameterCount count(arg_count);
3811 __ CallRuntime(Runtime::kCall, args->length());
3818 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3819 RegExpConstructResultStub stub(isolate());
3820 ZoneList<Expression*>* args = expr->arguments();
3821 DCHECK(args->length() == 3);
3833 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3834 ZoneList<Expression*>* args = expr->arguments();
3838 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value();
3840 Handle<FixedArray> jsfunction_result_caches(
3841 isolate()->native_context()->jsfunction_result_caches());
3842 if (jsfunction_result_caches->length() <= cache_id) {
3843 __ Abort(kAttemptToUseUndefinedCache);
3844 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
3852 Register cache = a1;
3862 Label done, not_found;
3869 __ daddu(a3, a3, at);
3872 __ Branch(¬_found,
ne, key, Operand(a2));
3877 __ bind(¬_found);
3880 __ CallRuntime(Runtime::kGetFromCache, 2);
3887 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3888 ZoneList<Expression*>* args = expr->arguments();
3891 Label materialize_true, materialize_false;
3892 Label* if_true =
NULL;
3893 Label* if_false =
NULL;
3894 Label* fall_through =
NULL;
3895 context()->PrepareTest(&materialize_true, &materialize_false,
3896 &if_true, &if_false, &fall_through);
3902 Split(
eq, a0, Operand(zero_reg), if_true, if_false, fall_through);
3904 context()->Plug(if_true, if_false);
3908 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3909 ZoneList<Expression*>* args = expr->arguments();
3910 DCHECK(args->length() == 1);
3913 __ AssertString(v0);
3916 __ IndexFromHash(v0, v0);
3922 void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) {
3923 Label bailout, done, one_char_separator, long_separator,
3924 non_trivial_array, not_size_one_array, loop,
3925 empty_separator_loop, one_char_separator_loop,
3926 one_char_separator_loop_entry, long_separator_loop;
3927 ZoneList<Expression*>* args = expr->arguments();
3928 DCHECK(args->length() == 2);
3933 Register array = v0;
3934 Register elements =
no_reg;
3935 Register result =
no_reg;
3936 Register separator = a1;
3937 Register array_length = a2;
3938 Register result_pos =
no_reg;
3939 Register string_length = a3;
3940 Register
string = a4;
3941 Register element = a5;
3942 Register elements_end = a6;
3943 Register scratch1 = a7;
3944 Register scratch2 = t1;
3945 Register scratch3 = t0;
3951 __ JumpIfSmi(array, &bailout);
3952 __ GetObjectType(array, scratch1, scratch2);
3956 __ CheckFastElements(scratch1, scratch2, &bailout);
3960 __ SmiUntag(array_length);
3961 __ Branch(&non_trivial_array,
ne, array_length, Operand(zero_reg));
3962 __ LoadRoot(v0, Heap::kempty_stringRootIndex);
3965 __ bind(&non_trivial_array);
3974 __ mov(string_length, zero_reg);
3978 __ Daddu(elements_end, element, elements_end);
3988 __ Assert(
gt, kNoEmptyArraysHereInEmitFastOneByteArrayJoin, array_length,
3994 __ JumpIfSmi(
string, &bailout);
3997 __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch1, scratch2, &bailout);
3999 __ AdduAndCheckForOverflow(string_length, string_length, scratch1, scratch3);
4000 __ BranchOnOverflow(&bailout, scratch3);
4001 __ Branch(&loop,
lt, element, Operand(elements_end));
4004 __ Branch(¬_size_one_array,
ne, array_length, Operand(1));
4008 __ bind(¬_size_one_array);
4017 __ JumpIfSmi(separator, &bailout);
4020 __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch1, scratch2, &bailout);
4026 __ Dsubu(string_length, string_length, Operand(scratch1));
4027 __ SmiUntag(scratch1);
4028 __ Dmul(scratch2, array_length, scratch1);
4031 __ dsra32(scratch1, scratch2, 0);
4032 __ Branch(&bailout,
ne, scratch2, Operand(zero_reg));
4033 __ SmiUntag(string_length);
4034 __ AdduAndCheckForOverflow(string_length, string_length, scratch2, scratch3);
4035 __ BranchOnOverflow(&bailout, scratch3);
4048 __ AllocateOneByteString(result, string_length, scratch1, scratch2,
4049 elements_end, &bailout);
4054 __ Daddu(elements_end, element, elements_end);
4055 result_pos = array_length;
4057 __ Daddu(result_pos,
4064 __ Branch(&one_char_separator,
eq, scratch1, Operand(at));
4065 __ Branch(&long_separator,
gt, scratch1, Operand(at));
4068 __ bind(&empty_separator_loop);
4078 __ SmiUntag(string_length);
4080 __ CopyBytes(
string, result_pos, string_length, scratch1);
4082 __ Branch(&empty_separator_loop,
lt, element, Operand(elements_end));
4087 __ bind(&one_char_separator);
4092 __ jmp(&one_char_separator_loop_entry);
4094 __ bind(&one_char_separator_loop);
4103 __ Daddu(result_pos, result_pos, 1);
4106 __ bind(&one_char_separator_loop_entry);
4110 __ SmiUntag(string_length);
4112 __ CopyBytes(
string, result_pos, string_length, scratch1);
4114 __ Branch(&one_char_separator_loop,
lt, element, Operand(elements_end));
4120 __ bind(&long_separator_loop);
4129 __ SmiUntag(string_length);
4133 __ CopyBytes(
string, result_pos, string_length, scratch1);
4135 __ bind(&long_separator);
4139 __ SmiUntag(string_length);
4141 __ CopyBytes(
string, result_pos, string_length, scratch1);
4143 __ Branch(&long_separator_loop,
lt, element, Operand(elements_end));
4148 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
4154 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
4155 DCHECK(expr->arguments()->length() == 0);
4156 ExternalReference debug_is_active =
4157 ExternalReference::debug_is_active_address(isolate());
4158 __ li(at, Operand(debug_is_active));
4165 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4166 if (expr->function() !=
NULL &&
4168 Comment cmnt(
masm_,
"[ InlineRuntimeCall");
4173 Comment cmnt(
masm_,
"[ CallRuntime");
4174 ZoneList<Expression*>* args = expr->arguments();
4175 int arg_count = args->length();
4177 if (expr->is_jsruntime()) {
4186 if (FLAG_vector_ics) {
4188 Operand(
Smi::FromInt(expr->CallRuntimeFeedbackSlot())));
4200 int arg_count = args->length();
4201 for (
int i = 0;
i < arg_count;
i++) {
4214 context()->DropAndPlug(1, v0);
4217 for (
int i = 0;
i < arg_count;
i++) {
4222 __ CallRuntime(expr->function(), arg_count);
4228 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4229 switch (expr->op()) {
4230 case Token::DELETE: {
4231 Comment cmnt(
masm_,
"[ UnaryOperation (DELETE)");
4232 Property*
property = expr->expression()->AsProperty();
4233 VariableProxy* proxy = expr->expression()->AsVariableProxy();
4235 if (property !=
NULL) {
4242 }
else if (proxy !=
NULL) {
4243 Variable* var = proxy->var();
4247 if (var->IsUnallocated()) {
4249 __ li(a1, Operand(var->name()));
4254 }
else if (var->IsStackAllocated() || var->IsContextSlot()) {
4257 context()->Plug(var->is_this());
4262 __ li(a2, Operand(var->name()));
4264 __ CallRuntime(Runtime::kDeleteLookupSlot, 2);
4277 Comment cmnt(
masm_,
"[ UnaryOperation (VOID)");
4279 context()->Plug(Heap::kUndefinedValueRootIndex);
4284 Comment cmnt(
masm_,
"[ UnaryOperation (NOT)");
4289 }
else if (
context()->IsTest()) {
4293 test->false_label(),
4295 test->fall_through());
4296 context()->Plug(test->true_label(), test->false_label());
4303 Label materialize_true, materialize_false, done;
4308 __ bind(&materialize_true);
4310 __ LoadRoot(v0, Heap::kTrueValueRootIndex);
4311 if (
context()->IsStackValue())
__ push(v0);
4313 __ bind(&materialize_false);
4315 __ LoadRoot(v0, Heap::kFalseValueRootIndex);
4316 if (
context()->IsStackValue())
__ push(v0);
4322 case Token::TYPEOF: {
4323 Comment cmnt(
masm_,
"[ UnaryOperation (TYPEOF)");
4324 { StackValueContext
context(
this);
4327 __ CallRuntime(Runtime::kTypeof, 1);
4338 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
4339 DCHECK(expr->expression()->IsValidReferenceExpression());
4341 Comment cmnt(
masm_,
"[ CountOperation");
4348 Property* prop = expr->expression()->AsProperty();
4358 DCHECK(expr->expression()->AsVariableProxy()->var() !=
NULL);
4359 AccumulatorValueContext
context(
this);
4363 if (expr->is_postfix() && !
context()->IsEffect()) {
4391 Label stub_call, done;
4392 JumpPatchSite patch_site(
masm_);
4394 int count_value = expr->op() == Token::INC ? 1 : -1;
4398 patch_site.EmitJumpIfNotSmi(v0, &slow);
4401 if (expr->is_postfix()) {
4406 switch (assign_type) {
4420 Register scratch1 = a1;
4421 Register scratch2 = a4;
4423 __ AdduAndCheckForOverflow(v0, v0, scratch1, scratch2);
4424 __ BranchOnNoOverflow(&done, scratch2);
4430 ToNumberStub convert_stub(isolate());
4431 __ CallStub(&convert_stub);
4434 if (expr->is_postfix()) {
4439 switch (assign_type) {
4453 __ bind(&stub_call);
4462 CallIC(code, expr->CountBinOpFeedbackId());
4463 patch_site.EmitPatchInfo();
4467 switch (assign_type) {
4469 if (expr->is_postfix()) {
4470 { EffectContext
context(
this);
4491 Operand(prop->key()->AsLiteral()->value()));
4495 if (expr->is_postfix()) {
4509 CodeFactory::KeyedStoreIC(isolate(),
strict_mode()).code();
4510 CallIC(ic, expr->CountStoreFeedbackId());
4512 if (expr->is_postfix()) {
4528 VariableProxy* proxy = expr->AsVariableProxy();
4529 if (proxy !=
NULL && proxy->var()->IsUnallocated()) {
4530 Comment cmnt(
masm_,
"[ Global variable");
4533 if (FLAG_vector_ics) {
4542 }
else if (proxy !=
NULL && proxy->var()->IsLookupSlot()) {
4543 Comment cmnt(
masm_,
"[ Lookup slot");
4551 __ li(a0, Operand(proxy->name()));
4553 __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
4565 Expression* sub_expr,
4566 Handle<String> check) {
4567 Label materialize_true, materialize_false;
4568 Label* if_true =
NULL;
4569 Label* if_false =
NULL;
4570 Label* fall_through =
NULL;
4571 context()->PrepareTest(&materialize_true, &materialize_false,
4572 &if_true, &if_false, &fall_through);
4574 { AccumulatorValueContext
context(
this);
4579 Factory* factory = isolate()->factory();
4581 __ JumpIfSmi(v0, if_true);
4583 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
4584 Split(
eq, v0, Operand(at), if_true, if_false, fall_through);
4586 __ JumpIfSmi(v0, if_false);
4588 __ GetObjectType(v0, v0, a1);
4592 Split(
eq, a1, Operand(zero_reg),
4593 if_true, if_false, fall_through);
4595 __ JumpIfSmi(v0, if_false);
4596 __ GetObjectType(v0, v0, a1);
4599 __ LoadRoot(at, Heap::kTrueValueRootIndex);
4600 __ Branch(if_true,
eq, v0, Operand(at));
4601 __ LoadRoot(at, Heap::kFalseValueRootIndex);
4602 Split(
eq, v0, Operand(at), if_true, if_false, fall_through);
4604 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
4605 __ Branch(if_true,
eq, v0, Operand(at));
4606 __ JumpIfSmi(v0, if_false);
4611 Split(
ne, a1, Operand(zero_reg), if_true, if_false, fall_through);
4613 __ JumpIfSmi(v0, if_false);
4615 __ GetObjectType(v0, v0, a1);
4618 if_true, if_false, fall_through);
4620 __ JumpIfSmi(v0, if_false);
4621 __ LoadRoot(at, Heap::kNullValueRootIndex);
4622 __ Branch(if_true,
eq, v0, Operand(at));
4624 __ GetObjectType(v0, v0, a1);
4631 Split(
eq, a1, Operand(zero_reg), if_true, if_false, fall_through);
4633 if (if_false != fall_through)
__ jmp(if_false);
4635 context()->Plug(if_true, if_false);
4639 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4640 Comment cmnt(
masm_,
"[ CompareOperation");
4649 Label materialize_true, materialize_false;
4650 Label* if_true =
NULL;
4651 Label* if_false =
NULL;
4652 Label* fall_through =
NULL;
4653 context()->PrepareTest(&materialize_true, &materialize_false,
4654 &if_true, &if_false, &fall_through);
4663 __ LoadRoot(a4, Heap::kTrueValueRootIndex);
4664 Split(
eq, v0, Operand(a4), if_true, if_false, fall_through);
4667 case Token::INSTANCEOF: {
4673 Split(
eq, v0, Operand(zero_reg), if_true, if_false, fall_through);
4684 JumpPatchSite patch_site(
masm_);
4685 if (inline_smi_code) {
4687 __ Or(a2, a0, Operand(a1));
4688 patch_site.EmitJumpIfNotSmi(a2, &slow_case);
4689 Split(
cc, a1, Operand(a0), if_true, if_false,
NULL);
4690 __ bind(&slow_case);
4694 Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
4695 CallIC(ic, expr->CompareOperationFeedbackId());
4696 patch_site.EmitPatchInfo();
4698 Split(
cc, v0, Operand(zero_reg), if_true, if_false, fall_through);
4704 context()->Plug(if_true, if_false);
4709 Expression* sub_expr,
4711 Label materialize_true, materialize_false;
4712 Label* if_true =
NULL;
4713 Label* if_false =
NULL;
4714 Label* fall_through =
NULL;
4715 context()->PrepareTest(&materialize_true, &materialize_false,
4716 &if_true, &if_false, &fall_through);
4721 if (expr->op() == Token::EQ_STRICT) {
4723 Heap::kNullValueRootIndex :
4724 Heap::kUndefinedValueRootIndex;
4725 __ LoadRoot(a1, nil_value);
4726 Split(
eq, a0, Operand(a1), if_true, if_false, fall_through);
4729 CallIC(ic, expr->CompareOperationFeedbackId());
4730 Split(
ne, v0, Operand(zero_reg), if_true, if_false, fall_through);
4732 context()->Plug(if_true, if_false);
4736 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
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());
4802 ExternalReference pending_message_obj =
4803 ExternalReference::address_of_pending_message_obj(isolate());
4804 __ li(at, Operand(pending_message_obj));
4808 ExternalReference has_pending_message =
4809 ExternalReference::address_of_has_pending_message(isolate());
4810 __ li(at, Operand(has_pending_message));
4815 ExternalReference pending_message_script =
4816 ExternalReference::address_of_pending_message_script(isolate());
4817 __ li(at, Operand(pending_message_script));
4827 ExternalReference pending_message_script =
4828 ExternalReference::address_of_pending_message_script(isolate());
4829 __ li(at, Operand(pending_message_script));
4834 ExternalReference has_pending_message =
4835 ExternalReference::address_of_has_pending_message(isolate());
4836 __ li(at, Operand(has_pending_message));
4840 ExternalReference pending_message_obj =
4841 ExternalReference::address_of_pending_message_obj(isolate());
4842 __ li(at, Operand(pending_message_obj));
4859 #define __ ACCESS_MASM(masm())
4863 int* context_length) {
4870 __ Drop(*stack_depth);
4871 if (*context_length > 0) {
4877 __ Call(finally_entry_);
4880 *context_length = 0;
4890 BackEdgeState target_state,
4891 Code* replacement_code) {
4893 Address branch_address =
pc - 8 * kInstrSize;
4894 CodePatcher patcher(branch_address, 1);
4896 switch (target_state) {
4907 patcher.masm()->slt(at, a3, zero_reg);
4909 case ON_STACK_REPLACEMENT:
4910 case OSR_AFTER_STACK_CHECK:
4920 patcher.masm()->daddiu(at, zero_reg, 1);
4923 Address pc_immediate_load_address =
pc - 6 * kInstrSize;
4927 replacement_code->entry());
4929 unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
4930 unoptimized_code, pc_immediate_load_address, replacement_code);
4936 Code* unoptimized_code,
4939 Address branch_address =
pc - 8 * kInstrSize;
4940 Address pc_immediate_load_address =
pc - 6 * kInstrSize;
4944 DCHECK(
reinterpret_cast<uint64_t
>(
4946 reinterpret_cast<uint64_t
>(
4947 isolate->builtins()->InterruptCheck()->entry()));
4953 if (
reinterpret_cast<uint64_t
>(
4955 reinterpret_cast<uint64_t
>(
4956 isolate->builtins()->OnStackReplacement()->entry())) {
4957 return ON_STACK_REPLACEMENT;
4960 DCHECK(
reinterpret_cast<uint64_t
>(
4962 reinterpret_cast<uint64_t
>(
4963 isolate->builtins()->OsrAfterStackCheck()->entry()));
4964 return OSR_AFTER_STACK_CHECK;
static const int kLengthOffset
static const int kInstrSize
static Address target_address_at(Address pc, ConstantPoolArray *constant_pool)
friend class BlockTrampolinePoolScope
int InstructionsGeneratedSince(Label *label)
static bool IsAddImmediate(Instr instr)
static const int kJSReturnSequenceInstructions
static void set_target_address_at(Address pc, ConstantPoolArray *constant_pool, Address target, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
static bool IsBeq(Instr instr)
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 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()
void mov(Register rd, Register rt)
void MultiPop(RegList regs)
void Jump(Register target, Condition cond=al)
static int CallSize(Register target, Condition cond=al)
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 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)
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
const int kPointerSizeLog2
@ LAST_NONCALLABLE_SPEC_OBJECT_TYPE
@ NUM_OF_CALLABLE_SPEC_OBJECT_TYPES
@ FIRST_NONCALLABLE_SPEC_OBJECT_TYPE
const uint32_t kOneByteStringTag
MemOperand FieldMemOperand(Register object, int offset)
bool IsImmutableVariableMode(VariableMode mode)
Condition NegateCondition(Condition cond)
static LifetimePosition Max(LifetimePosition a, LifetimePosition b)
kFeedbackVectorOffset flag
MemOperand GlobalObjectOperand()
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
@ RECORD_CONSTRUCTOR_TARGET
bool IsAligned(T value, U alignment)
void CopyBytes(uint8_t *target, uint8_t *source)
bool IsFastObjectElementsKind(ElementsKind kind)
Debugger support for the V8 JavaScript engine.
static Register from_code(int code)