30 #if defined(V8_TARGET_ARCH_X64)
39 #define DEFINE_COMPILE(type) \
40 void L##type::CompileToNative(LCodeGen* generator) { \
41 generator->Do##type(this); \
48 register_spills_[i] =
NULL;
51 double_register_spills_[i] =
NULL;
57 LOperand* spill_operand) {
58 ASSERT(spill_operand->IsStackSlot());
59 ASSERT(register_spills_[allocation_index] ==
NULL);
60 register_spills_[allocation_index] = spill_operand;
65 LOperand* spill_operand) {
66 ASSERT(spill_operand->IsDoubleStackSlot());
67 ASSERT(double_register_spills_[allocation_index] ==
NULL);
68 double_register_spills_[allocation_index] = spill_operand;
73 void LInstruction::VerifyCall() {
81 for (UseIterator it(
this); !it.Done(); it.Advance()) {
83 ASSERT(operand->HasFixedPolicy() ||
84 operand->IsUsedAtStart());
88 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
95 stream->Add(
"%s ", this->
Mnemonic());
115 for (
int i = 0; i < InputCount(); i++) {
116 if (i > 0) stream->Add(
" ");
131 stream->Add(
" Dead block replaced with B%d", rep->block_id());
137 for (
int i = 0; i < 4; i++) {
138 if (parallel_moves_[i] !=
NULL && !parallel_moves_[i]->
IsRedundant()) {
148 for (
int i = 0; i < 4; i++) {
150 if (parallel_moves_[i] !=
NULL) {
164 case Token::MOD:
return "mod-d";
177 case Token::MOD:
return "mod-t";
179 case Token::BIT_AND:
return "bit-and-t";
180 case Token::BIT_OR:
return "bit-or-t";
181 case Token::BIT_XOR:
return "bit-xor-t";
182 case Token::SHL:
return "sal-t";
183 case Token::SAR:
return "sar-t";
184 case Token::SHR:
return "shr-t";
222 stream->Add(
"if is_object(");
229 stream->Add(
"if is_string(");
236 stream->Add(
"if is_smi(");
243 stream->Add(
"if is_undetectable(");
250 stream->Add(
"if string_compare(");
258 stream->Add(
"if has_instance_type(");
265 stream->Add(
"if has_cached_array_index(");
272 stream->Add(
"if class_of_test(");
274 stream->Add(
", \"%o\") then B%d else B%d",
275 *hydrogen()->class_name(),
282 stream->Add(
"if typeof ");
284 stream->Add(
" == \"%s\" then B%d else B%d",
291 stream->Add(
"#%d / ",
arity());
296 stream->Add(
"/%s ", hydrogen()->OpName());
317 stream->Add(
" #%d / ",
arity());
322 stream->Add(
"[rcx] #%d / ",
arity());
327 SmartArrayPointer<char> name_string =
name()->ToCString();
328 stream->Add(
"%s #%d / ", *name_string,
arity());
333 SmartArrayPointer<char> name_string =
name()->ToCString();
334 stream->Add(
"%s #%d / ", *name_string,
arity());
339 stream->Add(
"#%d / ",
arity());
346 stream->Add(
" #%d / ",
arity());
353 stream->Add(
" length ");
356 stream->Add(
" index ");
401 stream->Add(
"] <- ");
410 stream->Add(
"] <- ");
419 stream->Add(
"] <- ");
430 LPlatformChunk* LChunkBuilder::Build() {
432 chunk_ =
new(zone()) LPlatformChunk(info(), graph());
433 HPhase phase(
"L_Building chunk", chunk_);
435 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
436 for (
int i = 0; i < blocks->length(); i++) {
437 HBasicBlock* next =
NULL;
438 if (i < blocks->length() - 1) next = blocks->at(i + 1);
439 DoBasicBlock(blocks->at(i), next);
440 if (is_aborted())
return NULL;
447 void LCodeGen::Abort(
const char* reason) {
448 info()->set_bailout_reason(reason);
453 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
459 LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
465 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
466 return Use(value, ToUnallocated(fixed_register));
470 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) {
471 return Use(value, ToUnallocated(reg));
475 LOperand* LChunkBuilder::UseRegister(HValue* value) {
480 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
487 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
492 LOperand* LChunkBuilder::Use(HValue* value) {
497 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
503 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
504 return value->IsConstant()
510 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
511 return value->IsConstant()
517 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
518 return value->IsConstant()
520 : UseRegister(value);
524 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
525 return value->IsConstant()
527 : UseRegisterAtStart(value);
531 LOperand* LChunkBuilder::UseAny(HValue* value) {
532 return value->IsConstant()
538 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
539 if (value->EmitAtUses()) {
541 VisitInstruction(instr);
543 operand->set_virtual_register(value->id());
548 template<
int I,
int T>
549 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
550 LUnallocated* result) {
551 result->set_virtual_register(current_instruction_->id());
552 instr->set_result(result);
557 template<
int I,
int T>
558 LInstruction* LChunkBuilder::DefineAsRegister(
559 LTemplateInstruction<1, I, T>* instr) {
565 template<
int I,
int T>
566 LInstruction* LChunkBuilder::DefineAsSpilled(
567 LTemplateInstruction<1, I, T>* instr,
574 template<
int I,
int T>
575 LInstruction* LChunkBuilder::DefineSameAsFirst(
576 LTemplateInstruction<1, I, T>* instr) {
582 template<
int I,
int T>
583 LInstruction* LChunkBuilder::DefineFixed(LTemplateInstruction<1, I, T>* instr,
585 return Define(instr, ToUnallocated(reg));
589 template<
int I,
int T>
590 LInstruction* LChunkBuilder::DefineFixedDouble(
591 LTemplateInstruction<1, I, T>* instr,
593 return Define(instr, ToUnallocated(reg));
597 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
598 HEnvironment* hydrogen_env = current_block_->last_environment();
599 int argument_index_accumulator = 0;
600 instr->set_environment(CreateEnvironment(hydrogen_env,
601 &argument_index_accumulator));
606 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
607 HInstruction* hinstr,
608 CanDeoptimize can_deoptimize) {
613 instr = AssignPointerMap(instr);
615 if (hinstr->HasObservableSideEffects()) {
616 ASSERT(hinstr->next()->IsSimulate());
618 ASSERT(instruction_pending_deoptimization_environment_ ==
NULL);
619 ASSERT(pending_deoptimization_ast_id_.IsNone());
620 instruction_pending_deoptimization_environment_ = instr;
621 pending_deoptimization_ast_id_ = sim->ast_id();
628 bool needs_environment =
629 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
630 !hinstr->HasObservableSideEffects();
631 if (needs_environment && !instr->HasEnvironment()) {
632 instr = AssignEnvironment(instr);
639 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
640 ASSERT(!instr->HasPointerMap());
641 instr->set_pointer_map(
new(zone()) LPointerMap(position_, zone()));
646 LUnallocated* LChunkBuilder::TempRegister() {
647 LUnallocated* operand =
649 operand->set_virtual_register(allocator_->GetVirtualRegister());
650 if (!allocator_->AllocationOk()) Abort(
"Not enough virtual registers.");
655 LOperand* LChunkBuilder::FixedTemp(Register reg) {
656 LUnallocated* operand = ToUnallocated(reg);
657 ASSERT(operand->HasFixedPolicy());
662 LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) {
663 LUnallocated* operand = ToUnallocated(reg);
664 ASSERT(operand->HasFixedPolicy());
669 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
670 return new(zone()) LLabel(instr->block());
674 LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
675 return AssignEnvironment(
new(zone()) LDeoptimize);
679 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
680 return AssignEnvironment(
new(zone()) LDeoptimize);
685 HBitwiseBinaryOperation* instr) {
686 if (instr->representation().IsTagged()) {
687 ASSERT(instr->left()->representation().IsTagged());
688 ASSERT(instr->right()->representation().IsTagged());
690 LOperand* left = UseFixed(instr->left(),
rdx);
691 LOperand* right = UseFixed(instr->right(),
rax);
692 LArithmeticT* result =
new(zone()) LArithmeticT(op, left, right);
693 return MarkAsCall(DefineFixed(result,
rax), instr);
696 ASSERT(instr->representation().IsInteger32());
697 ASSERT(instr->left()->representation().IsInteger32());
698 ASSERT(instr->right()->representation().IsInteger32());
699 LOperand* left = UseRegisterAtStart(instr->left());
701 HValue* right_value = instr->right();
702 LOperand* right =
NULL;
703 int constant_value = 0;
704 if (right_value->IsConstant()) {
706 right = chunk_->DefineConstantOperand(constant);
707 constant_value = constant->Integer32Value() & 0x1f;
709 right = UseFixed(right_value,
rcx);
714 bool does_deopt =
false;
715 if (op == Token::SHR && constant_value == 0) {
716 if (FLAG_opt_safe_uint32_operations) {
719 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
728 LInstruction* result =
729 DefineSameAsFirst(
new(zone()) LShiftI(op, left, right, does_deopt));
730 return does_deopt ? AssignEnvironment(result) : result;
734 LInstruction* LChunkBuilder::DoArithmeticD(
Token::Value op,
735 HArithmeticBinaryOperation* instr) {
736 ASSERT(instr->representation().IsDouble());
737 ASSERT(instr->left()->representation().IsDouble());
738 ASSERT(instr->right()->representation().IsDouble());
740 LOperand* left = UseRegisterAtStart(instr->left());
741 LOperand* right = UseRegisterAtStart(instr->right());
742 LArithmeticD* result =
new(zone()) LArithmeticD(op, left, right);
743 return DefineSameAsFirst(result);
747 LInstruction* LChunkBuilder::DoArithmeticT(
Token::Value op,
748 HArithmeticBinaryOperation* instr) {
754 HValue* left = instr->left();
755 HValue* right = instr->right();
756 ASSERT(left->representation().IsTagged());
757 ASSERT(right->representation().IsTagged());
758 LOperand* left_operand = UseFixed(left,
rdx);
759 LOperand* right_operand = UseFixed(right,
rax);
760 LArithmeticT* result =
761 new(zone()) LArithmeticT(op, left_operand, right_operand);
762 return MarkAsCall(DefineFixed(result,
rax), instr);
766 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
768 current_block_ = block;
769 next_block_ = next_block;
770 if (block->IsStartBlock()) {
771 block->UpdateEnvironment(graph_->start_environment());
773 }
else if (block->predecessors()->length() == 1) {
776 ASSERT(block->phis()->length() == 0);
777 HBasicBlock* pred = block->predecessors()->at(0);
778 HEnvironment* last_environment = pred->last_environment();
781 if (pred->end()->SecondSuccessor() ==
NULL) {
782 ASSERT(pred->end()->FirstSuccessor() == block);
784 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
785 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
786 last_environment = last_environment->Copy();
789 block->UpdateEnvironment(last_environment);
790 ASSERT(pred->argument_count() >= 0);
791 argument_count_ = pred->argument_count();
794 HBasicBlock* pred = block->predecessors()->at(0);
796 HEnvironment* last_environment = pred->last_environment();
797 for (
int i = 0; i < block->phis()->length(); ++i) {
798 HPhi* phi = block->phis()->at(i);
799 last_environment->SetValueAt(phi->merged_index(), phi);
801 for (
int i = 0; i < block->deleted_phis()->length(); ++i) {
802 last_environment->SetValueAt(block->deleted_phis()->at(i),
803 graph_->GetConstantUndefined());
805 block->UpdateEnvironment(last_environment);
807 argument_count_ = pred->argument_count();
809 HInstruction* current = block->first();
810 int start = chunk_->instructions()->length();
811 while (current !=
NULL && !is_aborted()) {
813 if (!current->EmitAtUses()) {
814 VisitInstruction(current);
816 current = current->next();
818 int end = chunk_->instructions()->length() - 1;
820 block->set_first_instruction_index(start);
821 block->set_last_instruction_index(end);
823 block->set_argument_count(argument_count_);
825 current_block_ =
NULL;
829 void LChunkBuilder::VisitInstruction(HInstruction* current) {
830 HInstruction* old_current = current_instruction_;
831 current_instruction_ = current;
832 if (current->has_position()) position_ = current->position();
833 LInstruction* instr = current->CompileToLithium(
this);
836 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
837 instr = AssignPointerMap(instr);
839 if (FLAG_stress_environments && !instr->HasEnvironment()) {
840 instr = AssignEnvironment(instr);
842 instr->set_hydrogen_value(current);
843 chunk_->AddInstruction(instr, current_block_);
845 current_instruction_ = old_current;
849 LEnvironment* LChunkBuilder::CreateEnvironment(
850 HEnvironment* hydrogen_env,
851 int* argument_index_accumulator) {
852 if (hydrogen_env ==
NULL)
return NULL;
854 LEnvironment* outer =
855 CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
856 BailoutId ast_id = hydrogen_env->ast_id();
857 ASSERT(!ast_id.IsNone() ||
859 int value_count = hydrogen_env->length();
860 LEnvironment* result =
new(zone()) LEnvironment(
861 hydrogen_env->closure(),
862 hydrogen_env->frame_type(),
864 hydrogen_env->parameter_count(),
868 hydrogen_env->entry(),
870 int argument_index = *argument_index_accumulator;
871 for (
int i = 0; i < value_count; ++i) {
872 if (hydrogen_env->is_special_index(i))
continue;
874 HValue* value = hydrogen_env->values()->at(i);
876 if (value->IsArgumentsObject()) {
878 }
else if (value->IsPushArgument()) {
879 op =
new(zone()) LArgument(argument_index++);
884 value->representation(),
889 *argument_index_accumulator = argument_index;
896 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
897 return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
901 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
902 HValue* value = instr->value();
903 if (value->EmitAtUses()) {
904 ASSERT(value->IsConstant());
905 ASSERT(!value->representation().IsDouble());
907 ? instr->FirstSuccessor()
908 : instr->SecondSuccessor();
909 return new(zone()) LGoto(successor->block_id());
912 LBranch* result =
new(zone()) LBranch(UseRegister(value));
916 HType type = value->type();
917 if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean()) {
918 return AssignEnvironment(result);
924 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
925 ASSERT(instr->value()->representation().IsTagged());
926 LOperand* value = UseRegisterAtStart(instr->value());
927 return new(zone()) LCmpMapAndBranch(value);
931 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
932 return DefineAsRegister(
new(zone()) LArgumentsLength(Use(length->value())));
936 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
937 return DefineAsRegister(
new(zone()) LArgumentsElements);
941 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
942 LOperand* left = UseFixed(instr->left(),
rax);
943 LOperand* right = UseFixed(instr->right(),
rdx);
944 LInstanceOf* result =
new(zone()) LInstanceOf(left, right);
945 return MarkAsCall(DefineFixed(result,
rax), instr);
949 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
950 HInstanceOfKnownGlobal* instr) {
951 LInstanceOfKnownGlobal* result =
952 new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(),
rax),
954 return MarkAsCall(DefineFixed(result,
rax), instr);
958 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
959 LOperand* receiver = UseRegister(instr->receiver());
960 LOperand*
function = UseRegisterAtStart(instr->function());
961 LWrapReceiver* result =
new(zone()) LWrapReceiver(receiver,
function);
962 return AssignEnvironment(DefineSameAsFirst(result));
966 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
967 LOperand*
function = UseFixed(instr->function(),
rdi);
968 LOperand* receiver = UseFixed(instr->receiver(),
rax);
969 LOperand* length = UseFixed(instr->length(),
rbx);
970 LOperand* elements = UseFixed(instr->elements(),
rcx);
971 LApplyArguments* result =
new(zone()) LApplyArguments(
function,
975 return MarkAsCall(DefineFixed(result,
rax), instr, CAN_DEOPTIMIZE_EAGERLY);
979 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
981 LOperand* argument = UseOrConstant(instr->argument());
982 return new(zone()) LPushArgument(argument);
986 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
987 return instr->HasNoUses()
989 : DefineAsRegister(
new(zone()) LThisFunction);
993 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
994 return instr->HasNoUses() ?
NULL : DefineAsRegister(
new(zone()) LContext);
998 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
999 LOperand* context = UseRegisterAtStart(instr->value());
1000 return DefineAsRegister(
new(zone()) LOuterContext(context));
1004 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1005 return MarkAsCall(
new(zone()) LDeclareGlobals, instr);
1009 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
1010 return DefineAsRegister(
new(zone()) LGlobalObject);
1014 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
1015 LOperand* global_object = UseRegisterAtStart(instr->value());
1016 return DefineAsRegister(
new(zone()) LGlobalReceiver(global_object));
1020 LInstruction* LChunkBuilder::DoCallConstantFunction(
1021 HCallConstantFunction* instr) {
1022 argument_count_ -= instr->argument_count();
1023 return MarkAsCall(DefineFixed(
new(zone()) LCallConstantFunction,
rax), instr);
1027 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1028 LOperand*
function = UseFixed(instr->function(),
rdi);
1029 argument_count_ -= instr->argument_count();
1030 LInvokeFunction* result =
new(zone()) LInvokeFunction(
function);
1031 return MarkAsCall(DefineFixed(result,
rax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1035 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1037 if (op == kMathLog || op == kMathSin || op == kMathCos || op == kMathTan) {
1038 LOperand* input = UseFixedDouble(instr->value(),
xmm1);
1039 LUnaryMathOperation* result =
new(zone()) LUnaryMathOperation(input);
1040 return MarkAsCall(DefineFixedDouble(result,
xmm1), instr);
1042 LOperand* input = UseRegisterAtStart(instr->value());
1043 LUnaryMathOperation* result =
new(zone()) LUnaryMathOperation(input);
1046 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1048 return AssignEnvironment(DefineAsRegister(result));
1050 return AssignEnvironment(DefineAsRegister(result));
1052 return DefineSameAsFirst(result);
1054 return DefineSameAsFirst(result);
1063 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1064 ASSERT(instr->key()->representation().IsTagged());
1065 LOperand* key = UseFixed(instr->key(),
rcx);
1066 argument_count_ -= instr->argument_count();
1067 LCallKeyed* result =
new(zone()) LCallKeyed(key);
1068 return MarkAsCall(DefineFixed(result,
rax), instr);
1072 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1073 argument_count_ -= instr->argument_count();
1074 return MarkAsCall(DefineFixed(
new(zone()) LCallNamed,
rax), instr);
1078 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1079 argument_count_ -= instr->argument_count();
1080 return MarkAsCall(DefineFixed(
new(zone()) LCallGlobal,
rax), instr);
1084 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1085 argument_count_ -= instr->argument_count();
1086 return MarkAsCall(DefineFixed(
new(zone()) LCallKnownGlobal,
rax), instr);
1090 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1091 LOperand* constructor = UseFixed(instr->constructor(),
rdi);
1092 argument_count_ -= instr->argument_count();
1093 LCallNew* result =
new(zone()) LCallNew(constructor);
1094 return MarkAsCall(DefineFixed(result,
rax), instr);
1098 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1099 LOperand*
function = UseFixed(instr->function(),
rdi);
1100 argument_count_ -= instr->argument_count();
1101 LCallFunction* result =
new(zone()) LCallFunction(
function);
1102 return MarkAsCall(DefineFixed(result,
rax), instr);
1106 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1107 argument_count_ -= instr->argument_count();
1108 return MarkAsCall(DefineFixed(
new(zone()) LCallRuntime,
rax), instr);
1112 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1113 return DoShift(Token::SHR, instr);
1117 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1118 return DoShift(Token::SAR, instr);
1122 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1123 return DoShift(Token::SHL, instr);
1127 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1128 if (instr->representation().IsInteger32()) {
1129 ASSERT(instr->left()->representation().IsInteger32());
1130 ASSERT(instr->right()->representation().IsInteger32());
1132 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1133 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1134 return DefineSameAsFirst(
new(zone()) LBitI(left, right));
1136 ASSERT(instr->representation().IsTagged());
1137 ASSERT(instr->left()->representation().IsTagged());
1138 ASSERT(instr->right()->representation().IsTagged());
1140 LOperand* left = UseFixed(instr->left(),
rdx);
1141 LOperand* right = UseFixed(instr->right(),
rax);
1142 LArithmeticT* result =
new(zone()) LArithmeticT(instr->op(), left, right);
1143 return MarkAsCall(DefineFixed(result,
rax), instr);
1148 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1149 ASSERT(instr->value()->representation().IsInteger32());
1150 ASSERT(instr->representation().IsInteger32());
1151 if (instr->HasNoUses())
return NULL;
1152 LOperand* input = UseRegisterAtStart(instr->value());
1153 LBitNotI* result =
new(zone()) LBitNotI(input);
1154 return DefineSameAsFirst(result);
1158 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1159 if (instr->representation().IsDouble()) {
1161 }
else if (instr->representation().IsInteger32()) {
1164 LOperand* temp = FixedTemp(
rdx);
1165 LOperand* dividend = UseFixed(instr->left(),
rax);
1166 LOperand* divisor = UseRegister(instr->right());
1167 LDivI* result =
new(zone()) LDivI(dividend, divisor, temp);
1168 return AssignEnvironment(DefineFixed(result,
rax));
1170 ASSERT(instr->representation().IsTagged());
1176 HValue* LChunkBuilder::SimplifiedDividendForMathFloorOfDiv(HValue* dividend) {
1178 if (dividend->representation().IsInteger32()) {
1181 }
else if (dividend->IsChange() &&
1189 HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
1190 if (divisor->IsConstant() &&
1194 divisor->block()->zone());
1200 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1201 HValue* right = instr->right();
1203 LOperand* divisor = chunk_->DefineConstantOperand(
HConstant::cast(right));
1205 if (divisor_si == 0) {
1206 LOperand* dividend = UseRegister(instr->left());
1207 return AssignEnvironment(DefineAsRegister(
1208 new(zone()) LMathFloorOfDiv(dividend, divisor,
NULL)));
1210 LOperand* dividend = UseRegisterAtStart(instr->left());
1211 LInstruction* result = DefineAsRegister(
1212 new(zone()) LMathFloorOfDiv(dividend, divisor,
NULL));
1213 return divisor_si < 0 ? AssignEnvironment(result) : result;
1216 LOperand* dividend = UseRegisterAtStart(instr->left());
1217 LOperand* temp = TempRegister();
1218 LInstruction* result = DefineAsRegister(
1219 new(zone()) LMathFloorOfDiv(dividend, divisor, temp));
1220 return divisor_si < 0 ? AssignEnvironment(result) : result;
1225 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1226 if (instr->representation().IsInteger32()) {
1227 ASSERT(instr->left()->representation().IsInteger32());
1228 ASSERT(instr->right()->representation().IsInteger32());
1230 LInstruction* result;
1231 if (instr->HasPowerOf2Divisor()) {
1233 LOperand* value = UseRegisterAtStart(instr->left());
1235 new(zone()) LModI(value, UseOrConstant(instr->right()),
NULL);
1236 result = DefineSameAsFirst(mod);
1240 LOperand* temp = FixedTemp(
rdx);
1241 LOperand* value = UseFixed(instr->left(),
rax);
1242 LOperand* divisor = UseRegister(instr->right());
1243 LModI* mod =
new(zone()) LModI(value, divisor, temp);
1244 result = DefineFixed(mod,
rdx);
1249 ? AssignEnvironment(result)
1251 }
else if (instr->representation().IsTagged()) {
1252 return DoArithmeticT(Token::MOD, instr);
1254 ASSERT(instr->representation().IsDouble());
1258 LOperand* left = UseFixedDouble(instr->left(),
xmm2);
1259 LOperand* right = UseFixedDouble(instr->right(),
xmm1);
1260 LArithmeticD* result =
new(zone()) LArithmeticD(Token::MOD, left, right);
1261 return MarkAsCall(DefineFixedDouble(result,
xmm1), instr);
1266 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1267 if (instr->representation().IsInteger32()) {
1268 ASSERT(instr->left()->representation().IsInteger32());
1269 ASSERT(instr->right()->representation().IsInteger32());
1270 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1271 LOperand* right = UseOrConstant(instr->MostConstantOperand());
1272 LMulI* mul =
new(zone()) LMulI(left, right);
1275 AssignEnvironment(mul);
1277 return DefineSameAsFirst(mul);
1278 }
else if (instr->representation().IsDouble()) {
1281 ASSERT(instr->representation().IsTagged());
1287 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1288 if (instr->representation().IsInteger32()) {
1289 ASSERT(instr->left()->representation().IsInteger32());
1290 ASSERT(instr->right()->representation().IsInteger32());
1291 LOperand* left = UseRegisterAtStart(instr->left());
1292 LOperand* right = UseOrConstantAtStart(instr->right());
1293 LSubI* sub =
new(zone()) LSubI(left, right);
1294 LInstruction* result = DefineSameAsFirst(sub);
1296 result = AssignEnvironment(result);
1299 }
else if (instr->representation().IsDouble()) {
1302 ASSERT(instr->representation().IsTagged());
1308 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1309 if (instr->representation().IsInteger32()) {
1310 ASSERT(instr->left()->representation().IsInteger32());
1311 ASSERT(instr->right()->representation().IsInteger32());
1312 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1313 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1314 LAddI* add =
new(zone()) LAddI(left, right);
1315 LInstruction* result = DefineSameAsFirst(add);
1317 result = AssignEnvironment(result);
1320 }
else if (instr->representation().IsDouble()) {
1323 ASSERT(instr->representation().IsTagged());
1330 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1331 LOperand* left =
NULL;
1332 LOperand* right =
NULL;
1333 if (instr->representation().IsInteger32()) {
1334 ASSERT(instr->left()->representation().IsInteger32());
1335 ASSERT(instr->right()->representation().IsInteger32());
1336 left = UseRegisterAtStart(instr->LeastConstantOperand());
1337 right = UseOrConstantAtStart(instr->MostConstantOperand());
1339 ASSERT(instr->representation().IsDouble());
1340 ASSERT(instr->left()->representation().IsDouble());
1341 ASSERT(instr->right()->representation().IsDouble());
1342 left = UseRegisterAtStart(instr->left());
1343 right = UseRegisterAtStart(instr->right());
1345 LMathMinMax* minmax =
new(zone()) LMathMinMax(left, right);
1346 return DefineSameAsFirst(minmax);
1350 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1351 ASSERT(instr->representation().IsDouble());
1354 Representation exponent_type = instr->right()->representation();
1355 ASSERT(instr->left()->representation().IsDouble());
1356 LOperand* left = UseFixedDouble(instr->left(),
xmm2);
1357 LOperand* right = exponent_type.IsDouble() ?
1358 UseFixedDouble(instr->right(),
xmm1) :
1360 UseFixed(instr->right(),
rdx);
1362 UseFixed(instr->right(),
rdi);
1364 LPower* result =
new(zone()) LPower(left, right);
1365 return MarkAsCall(DefineFixedDouble(result,
xmm3), instr,
1366 CAN_DEOPTIMIZE_EAGERLY);
1370 LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
1371 ASSERT(instr->representation().IsDouble());
1372 ASSERT(instr->global_object()->representation().IsTagged());
1374 LOperand* global_object = UseFixed(instr->global_object(),
rcx);
1376 LOperand* global_object = UseFixed(instr->global_object(),
rdi);
1378 LRandom* result =
new(zone()) LRandom(global_object);
1379 return MarkAsCall(DefineFixedDouble(result,
xmm1), instr);
1383 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1384 ASSERT(instr->left()->representation().IsTagged());
1385 ASSERT(instr->right()->representation().IsTagged());
1386 LOperand* left = UseFixed(instr->left(),
rdx);
1387 LOperand* right = UseFixed(instr->right(),
rax);
1388 LCmpT* result =
new(zone()) LCmpT(left, right);
1389 return MarkAsCall(DefineFixed(result,
rax), instr);
1393 LInstruction* LChunkBuilder::DoCompareIDAndBranch(
1394 HCompareIDAndBranch* instr) {
1395 Representation r = instr->GetInputRepresentation();
1396 if (r.IsInteger32()) {
1397 ASSERT(instr->left()->representation().IsInteger32());
1398 ASSERT(instr->right()->representation().IsInteger32());
1399 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1400 LOperand* right = UseOrConstantAtStart(instr->right());
1401 return new(zone()) LCmpIDAndBranch(left, right);
1404 ASSERT(instr->left()->representation().IsDouble());
1405 ASSERT(instr->right()->representation().IsDouble());
1408 if (instr->left()->IsConstant() && instr->right()->IsConstant()) {
1409 left = UseRegisterOrConstantAtStart(instr->left());
1410 right = UseRegisterOrConstantAtStart(instr->right());
1412 left = UseRegisterAtStart(instr->left());
1413 right = UseRegisterAtStart(instr->right());
1415 return new(zone()) LCmpIDAndBranch(left, right);
1420 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1421 HCompareObjectEqAndBranch* instr) {
1422 LOperand* left = UseRegisterAtStart(instr->left());
1423 LOperand* right = UseRegisterAtStart(instr->right());
1424 return new(zone()) LCmpObjectEqAndBranch(left, right);
1428 LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
1429 HCompareConstantEqAndBranch* instr) {
1430 LOperand* value = UseRegisterAtStart(instr->value());
1431 return new(zone()) LCmpConstantEqAndBranch(value);
1435 LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) {
1436 ASSERT(instr->value()->representation().IsTagged());
1438 return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value()), temp);
1442 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1443 ASSERT(instr->value()->representation().IsTagged());
1444 return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()));
1448 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1449 ASSERT(instr->value()->representation().IsTagged());
1450 LOperand* value = UseRegisterAtStart(instr->value());
1451 LOperand* temp = TempRegister();
1452 return new(zone()) LIsStringAndBranch(value, temp);
1456 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1457 ASSERT(instr->value()->representation().IsTagged());
1458 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1462 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1463 HIsUndetectableAndBranch* instr) {
1464 ASSERT(instr->value()->representation().IsTagged());
1465 LOperand* value = UseRegisterAtStart(instr->value());
1466 LOperand* temp = TempRegister();
1467 return new(zone()) LIsUndetectableAndBranch(value, temp);
1471 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1472 HStringCompareAndBranch* instr) {
1474 ASSERT(instr->left()->representation().IsTagged());
1475 ASSERT(instr->right()->representation().IsTagged());
1476 LOperand* left = UseFixed(instr->left(),
rdx);
1477 LOperand* right = UseFixed(instr->right(),
rax);
1478 LStringCompareAndBranch* result =
1479 new(zone()) LStringCompareAndBranch(left, right);
1481 return MarkAsCall(result, instr);
1485 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1486 HHasInstanceTypeAndBranch* instr) {
1487 ASSERT(instr->value()->representation().IsTagged());
1488 LOperand* value = UseRegisterAtStart(instr->value());
1489 return new(zone()) LHasInstanceTypeAndBranch(value);
1493 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1494 HGetCachedArrayIndex* instr) {
1495 ASSERT(instr->value()->representation().IsTagged());
1496 LOperand* value = UseRegisterAtStart(instr->value());
1498 return DefineAsRegister(
new(zone()) LGetCachedArrayIndex(value));
1502 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1503 HHasCachedArrayIndexAndBranch* instr) {
1504 ASSERT(instr->value()->representation().IsTagged());
1505 LOperand* value = UseRegisterAtStart(instr->value());
1506 return new(zone()) LHasCachedArrayIndexAndBranch(value);
1510 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1511 HClassOfTestAndBranch* instr) {
1512 LOperand* value = UseRegister(instr->value());
1513 return new(zone()) LClassOfTestAndBranch(value,
1519 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1520 LOperand* array = UseRegisterAtStart(instr->value());
1521 return DefineAsRegister(
new(zone()) LJSArrayLength(array));
1525 LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
1526 HFixedArrayBaseLength* instr) {
1527 LOperand* array = UseRegisterAtStart(instr->value());
1528 return DefineAsRegister(
new(zone()) LFixedArrayBaseLength(array));
1532 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1533 LOperand* map = UseRegisterAtStart(instr->value());
1534 return DefineAsRegister(
new(zone()) LMapEnumLength(map));
1538 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1539 LOperand*
object = UseRegisterAtStart(instr->value());
1540 return DefineAsRegister(
new(zone()) LElementsKind(
object));
1544 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1545 LOperand*
object = UseRegister(instr->value());
1546 LValueOf* result =
new(zone()) LValueOf(
object);
1547 return DefineSameAsFirst(result);
1551 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1552 LOperand*
object = UseFixed(instr->value(),
rax);
1553 LDateField* result =
new(zone()) LDateField(
object, instr->index());
1554 return MarkAsCall(DefineFixed(result,
rax), instr, CAN_DEOPTIMIZE_EAGERLY);
1558 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1559 LOperand* value = UseRegisterOrConstantAtStart(instr->index());
1560 LOperand* length = Use(instr->length());
1561 return AssignEnvironment(
new(zone()) LBoundsCheck(value, length));
1565 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1572 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1573 LOperand* value = UseFixed(instr->value(),
rax);
1574 return MarkAsCall(
new(zone()) LThrow(value), instr);
1578 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1583 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1591 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1592 Representation from = instr->from();
1593 Representation to = instr->to();
1594 if (from.IsTagged()) {
1595 if (to.IsDouble()) {
1596 LOperand* value = UseRegister(instr->value());
1597 LNumberUntagD* res =
new(zone()) LNumberUntagD(value);
1598 return AssignEnvironment(DefineAsRegister(res));
1600 ASSERT(to.IsInteger32());
1601 LOperand* value = UseRegister(instr->value());
1602 if (instr->value()->type().IsSmi()) {
1603 return DefineSameAsFirst(
new(zone()) LSmiUntag(value,
false));
1605 bool truncating = instr->CanTruncateToInt32();
1606 LOperand* xmm_temp = truncating ?
NULL : FixedTemp(
xmm1);
1607 LTaggedToI* res =
new(zone()) LTaggedToI(value, xmm_temp);
1608 return AssignEnvironment(DefineSameAsFirst(res));
1611 }
else if (from.IsDouble()) {
1612 if (to.IsTagged()) {
1613 LOperand* value = UseRegister(instr->value());
1614 LOperand* temp = TempRegister();
1617 LUnallocated* result_temp = TempRegister();
1618 LNumberTagD* result =
new(zone()) LNumberTagD(value, temp);
1619 return AssignPointerMap(Define(result, result_temp));
1621 ASSERT(to.IsInteger32());
1622 LOperand* value = UseRegister(instr->value());
1623 return AssignEnvironment(DefineAsRegister(
new(zone()) LDoubleToI(value)));
1625 }
else if (from.IsInteger32()) {
1626 if (to.IsTagged()) {
1627 HValue* val = instr->value();
1628 LOperand* value = UseRegister(val);
1630 LOperand* temp = FixedTemp(
xmm1);
1631 LNumberTagU* result =
new(zone()) LNumberTagU(value, temp);
1632 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1633 }
else if (val->HasRange() && val->range()->IsInSmiRange()) {
1634 return DefineSameAsFirst(
new(zone()) LSmiTag(value));
1636 LNumberTagI* result =
new(zone()) LNumberTagI(value);
1637 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1641 LOperand* temp = FixedTemp(
xmm1);
1642 return DefineAsRegister(
1643 new(zone()) LUint32ToDouble(UseRegister(instr->value()), temp));
1646 LOperand* value = Use(instr->value());
1647 return DefineAsRegister(
new(zone()) LInteger32ToDouble(value));
1656 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1657 LOperand* value = UseRegisterAtStart(instr->value());
1658 return AssignEnvironment(
new(zone()) LCheckNonSmi(value));
1662 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1663 LOperand* value = UseRegisterAtStart(instr->value());
1664 LCheckInstanceType* result =
new(zone()) LCheckInstanceType(value);
1665 return AssignEnvironment(result);
1669 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
1670 LOperand* temp = TempRegister();
1671 LCheckPrototypeMaps* result =
new(zone()) LCheckPrototypeMaps(temp);
1672 return AssignEnvironment(result);
1676 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1677 LOperand* value = UseRegisterAtStart(instr->value());
1678 return AssignEnvironment(
new(zone()) LCheckSmi(value));
1682 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1683 LOperand* value = UseRegisterAtStart(instr->value());
1684 return AssignEnvironment(
new(zone()) LCheckFunction(value));
1688 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
1689 LOperand* value = UseRegisterAtStart(instr->value());
1690 LCheckMaps* result =
new(zone()) LCheckMaps(value);
1691 return AssignEnvironment(result);
1695 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1696 HValue* value = instr->value();
1697 Representation input_rep = value->representation();
1698 LOperand* reg = UseRegister(value);
1699 if (input_rep.IsDouble()) {
1700 return DefineAsRegister(
new(zone()) LClampDToUint8(reg));
1701 }
else if (input_rep.IsInteger32()) {
1702 return DefineSameAsFirst(
new(zone()) LClampIToUint8(reg));
1704 ASSERT(input_rep.IsTagged());
1707 LClampTToUint8* result =
new(zone()) LClampTToUint8(reg,
1709 return AssignEnvironment(DefineSameAsFirst(result));
1714 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1715 return new(zone()) LReturn(UseFixed(instr->value(),
rax));
1719 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1720 Representation r = instr->representation();
1721 if (r.IsInteger32()) {
1722 return DefineAsRegister(
new(zone()) LConstantI);
1723 }
else if (r.IsDouble()) {
1724 LOperand* temp = TempRegister();
1725 return DefineAsRegister(
new(zone()) LConstantD(temp));
1726 }
else if (r.IsTagged()) {
1727 return DefineAsRegister(
new(zone()) LConstantT);
1735 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
1736 LLoadGlobalCell* result =
new(zone()) LLoadGlobalCell;
1737 return instr->RequiresHoleCheck()
1738 ? AssignEnvironment(DefineAsRegister(result))
1739 : DefineAsRegister(result);
1743 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1744 LOperand* global_object = UseFixed(instr->global_object(),
rax);
1745 LLoadGlobalGeneric* result =
new(zone()) LLoadGlobalGeneric(global_object);
1746 return MarkAsCall(DefineFixed(result,
rax), instr);
1750 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
1751 LOperand* value = UseRegister(instr->value());
1754 return instr->RequiresHoleCheck()
1755 ? AssignEnvironment(
new(zone()) LStoreGlobalCell(value, TempRegister()))
1756 : new(zone()) LStoreGlobalCell(value,
NULL);
1760 LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
1761 LOperand* global_object = UseFixed(instr->global_object(),
rdx);
1762 LOperand* value = UseFixed(instr->value(),
rax);
1763 LStoreGlobalGeneric* result =
new(zone()) LStoreGlobalGeneric(global_object,
1765 return MarkAsCall(result, instr);
1769 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1770 LOperand* context = UseRegisterAtStart(instr->value());
1771 LInstruction* result =
1772 DefineAsRegister(
new(zone()) LLoadContextSlot(context));
1773 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1777 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
1781 if (instr->NeedsWriteBarrier()) {
1782 context = UseTempRegister(instr->context());
1783 value = UseTempRegister(instr->value());
1784 temp = TempRegister();
1786 context = UseRegister(instr->context());
1787 value = UseRegister(instr->value());
1790 LInstruction* result =
new(zone()) LStoreContextSlot(context, value, temp);
1791 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1795 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1796 ASSERT(instr->representation().IsTagged());
1797 LOperand* obj = UseRegisterAtStart(instr->object());
1798 return DefineAsRegister(
new(zone()) LLoadNamedField(obj));
1802 LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
1803 HLoadNamedFieldPolymorphic* instr) {
1804 ASSERT(instr->representation().IsTagged());
1805 if (instr->need_generic()) {
1806 LOperand* obj = UseFixed(instr->object(),
rax);
1807 LLoadNamedFieldPolymorphic* result =
1808 new(zone()) LLoadNamedFieldPolymorphic(obj);
1809 return MarkAsCall(DefineFixed(result,
rax), instr);
1811 LOperand* obj = UseRegisterAtStart(instr->object());
1812 LLoadNamedFieldPolymorphic* result =
1813 new(zone()) LLoadNamedFieldPolymorphic(obj);
1814 return AssignEnvironment(DefineAsRegister(result));
1819 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1820 LOperand*
object = UseFixed(instr->object(),
rax);
1821 LLoadNamedGeneric* result =
new(zone()) LLoadNamedGeneric(
object);
1822 return MarkAsCall(DefineFixed(result,
rax), instr);
1826 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1827 HLoadFunctionPrototype* instr) {
1828 return AssignEnvironment(DefineAsRegister(
1829 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
1833 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1834 LOperand* input = UseRegisterAtStart(instr->value());
1835 return DefineAsRegister(
new(zone()) LLoadElements(input));
1839 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
1840 HLoadExternalArrayPointer* instr) {
1841 LOperand* input = UseRegisterAtStart(instr->value());
1842 return DefineAsRegister(
new(zone()) LLoadExternalArrayPointer(input));
1846 LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1847 HLoadKeyedFastElement* instr) {
1848 ASSERT(instr->representation().IsTagged());
1849 ASSERT(instr->key()->representation().IsInteger32() ||
1850 instr->key()->representation().IsTagged());
1851 LOperand* obj = UseRegisterAtStart(instr->object());
1852 bool clobbers_key = instr->key()->representation().IsTagged();
1853 LOperand* key = clobbers_key
1854 ? UseTempRegister(instr->key())
1855 : UseRegisterOrConstantAtStart(instr->key());
1856 LLoadKeyedFastElement* result =
1857 new(zone()) LLoadKeyedFastElement(obj, key);
1858 if (instr->RequiresHoleCheck()) AssignEnvironment(result);
1859 return DefineAsRegister(result);
1863 LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
1864 HLoadKeyedFastDoubleElement* instr) {
1865 ASSERT(instr->representation().IsDouble());
1866 ASSERT(instr->key()->representation().IsInteger32() ||
1867 instr->key()->representation().IsTagged());
1868 LOperand* elements = UseRegisterAtStart(instr->elements());
1869 bool clobbers_key = instr->key()->representation().IsTagged();
1870 LOperand* key = clobbers_key
1871 ? UseTempRegister(instr->key())
1872 : UseRegisterOrConstantAtStart(instr->key());
1873 LLoadKeyedFastDoubleElement* result =
1874 new(zone()) LLoadKeyedFastDoubleElement(elements, key);
1875 return AssignEnvironment(DefineAsRegister(result));
1879 LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
1880 HLoadKeyedSpecializedArrayElement* instr) {
1883 (instr->representation().IsInteger32() &&
1886 (instr->representation().IsDouble() &&
1889 ASSERT(instr->key()->representation().IsInteger32() ||
1890 instr->key()->representation().IsTagged());
1891 LOperand* external_pointer = UseRegister(instr->external_pointer());
1892 bool clobbers_key = instr->key()->representation().IsTagged();
1893 LOperand* key = clobbers_key
1894 ? UseTempRegister(instr->key())
1895 : UseRegisterOrConstantAtStart(instr->key());
1896 LLoadKeyedSpecializedArrayElement* result =
1897 new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
1898 LInstruction* load_instr = DefineAsRegister(result);
1902 AssignEnvironment(load_instr) : load_instr;
1906 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1907 LOperand*
object = UseFixed(instr->object(),
rdx);
1908 LOperand* key = UseFixed(instr->key(),
rax);
1910 LLoadKeyedGeneric* result =
new(zone()) LLoadKeyedGeneric(
object, key);
1911 return MarkAsCall(DefineFixed(result,
rax), instr);
1915 LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1916 HStoreKeyedFastElement* instr) {
1917 bool needs_write_barrier = instr->NeedsWriteBarrier();
1918 ASSERT(instr->value()->representation().IsTagged());
1919 ASSERT(instr->object()->representation().IsTagged());
1920 ASSERT(instr->key()->representation().IsInteger32() ||
1921 instr->key()->representation().IsTagged());
1923 LOperand* obj = UseTempRegister(instr->object());
1924 LOperand* val = needs_write_barrier
1925 ? UseTempRegister(instr->value())
1926 : UseRegisterAtStart(instr->value());
1927 bool clobbers_key = needs_write_barrier ||
1928 instr->key()->representation().IsTagged();
1929 LOperand* key = clobbers_key
1930 ? UseTempRegister(instr->key())
1931 : UseRegisterOrConstantAtStart(instr->key());
1932 return new(zone()) LStoreKeyedFastElement(obj, key, val);
1936 LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
1937 HStoreKeyedFastDoubleElement* instr) {
1938 ASSERT(instr->value()->representation().IsDouble());
1939 ASSERT(instr->elements()->representation().IsTagged());
1940 ASSERT(instr->key()->representation().IsInteger32() ||
1941 instr->key()->representation().IsTagged());
1943 LOperand* elements = UseRegisterAtStart(instr->elements());
1944 LOperand* val = UseTempRegister(instr->value());
1945 bool clobbers_key = instr->key()->representation().IsTagged();
1946 LOperand* key = clobbers_key
1947 ? UseTempRegister(instr->key())
1948 : UseRegisterOrConstantAtStart(instr->key());
1949 return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
1953 LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
1954 HStoreKeyedSpecializedArrayElement* instr) {
1957 (instr->value()->representation().IsInteger32() &&
1960 (instr->value()->representation().IsDouble() &&
1963 ASSERT(instr->external_pointer()->representation().IsExternal());
1964 ASSERT(instr->key()->representation().IsInteger32() ||
1965 instr->key()->representation().IsTagged());
1967 LOperand* external_pointer = UseRegister(instr->external_pointer());
1968 bool val_is_temp_register =
1971 LOperand* val = val_is_temp_register
1972 ? UseTempRegister(instr->value())
1973 : UseRegister(instr->value());
1974 bool clobbers_key = instr->key()->representation().IsTagged();
1975 LOperand* key = clobbers_key
1976 ? UseTempRegister(instr->key())
1977 : UseRegisterOrConstantAtStart(instr->key());
1978 return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
1983 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1984 LOperand*
object = UseFixed(instr->object(),
rdx);
1985 LOperand* key = UseFixed(instr->key(),
rcx);
1986 LOperand* value = UseFixed(instr->value(),
rax);
1988 ASSERT(instr->object()->representation().IsTagged());
1989 ASSERT(instr->key()->representation().IsTagged());
1990 ASSERT(instr->value()->representation().IsTagged());
1992 LStoreKeyedGeneric* result =
1993 new(zone()) LStoreKeyedGeneric(
object, key, value);
1994 return MarkAsCall(result, instr);
1998 LInstruction* LChunkBuilder::DoTransitionElementsKind(
1999 HTransitionElementsKind* instr) {
2000 ElementsKind from_kind = instr->original_map()->elements_kind();
2001 ElementsKind to_kind = instr->transitioned_map()->elements_kind();
2003 LOperand*
object = UseRegister(instr->object());
2004 LOperand* new_map_reg = TempRegister();
2005 LOperand* temp_reg = TempRegister();
2006 LTransitionElementsKind* result =
2007 new(zone()) LTransitionElementsKind(
object, new_map_reg, temp_reg);
2008 return DefineSameAsFirst(result);
2010 LOperand*
object = UseFixed(instr->object(),
rax);
2011 LOperand* fixed_object_reg = FixedTemp(
rdx);
2012 LOperand* new_map_reg = FixedTemp(
rbx);
2013 LTransitionElementsKind* result =
2014 new(zone()) LTransitionElementsKind(
object,
2017 return MarkAsCall(DefineFixed(result,
rax), instr);
2022 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2023 bool needs_write_barrier = instr->NeedsWriteBarrier();
2024 bool needs_write_barrier_for_map = !instr->transition().is_null() &&
2025 instr->NeedsWriteBarrierForMap();
2028 if (needs_write_barrier) {
2029 obj = instr->is_in_object()
2030 ? UseRegister(instr->object())
2031 : UseTempRegister(instr->object());
2033 obj = needs_write_barrier_for_map
2034 ? UseRegister(instr->object())
2035 : UseRegisterAtStart(instr->object());
2038 LOperand* val = needs_write_barrier
2039 ? UseTempRegister(instr->value())
2040 : UseRegister(instr->value());
2044 LOperand* temp = (!instr->is_in_object() || needs_write_barrier ||
2045 needs_write_barrier_for_map) ? TempRegister() :
NULL;
2047 return new(zone()) LStoreNamedField(obj, val, temp);
2051 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2052 LOperand*
object = UseFixed(instr->object(),
rdx);
2053 LOperand* value = UseFixed(instr->value(),
rax);
2055 LStoreNamedGeneric* result =
new(zone()) LStoreNamedGeneric(
object, value);
2056 return MarkAsCall(result, instr);
2060 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2061 LOperand* left = UseOrConstantAtStart(instr->left());
2062 LOperand* right = UseOrConstantAtStart(instr->right());
2063 return MarkAsCall(DefineFixed(
new(zone()) LStringAdd(left, right),
rax),
2068 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2069 LOperand*
string = UseTempRegister(instr->string());
2070 LOperand* index = UseTempRegister(instr->index());
2071 LStringCharCodeAt* result =
new(zone()) LStringCharCodeAt(
string, index);
2072 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2076 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2077 LOperand* char_code = UseRegister(instr->value());
2078 LStringCharFromCode* result =
new(zone()) LStringCharFromCode(char_code);
2079 return AssignPointerMap(DefineAsRegister(result));
2083 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
2084 LOperand*
string = UseRegisterAtStart(instr->value());
2085 return DefineAsRegister(
new(zone()) LStringLength(
string));
2089 LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
2090 LAllocateObject* result =
new(zone()) LAllocateObject(TempRegister());
2091 return AssignPointerMap(DefineAsRegister(result));
2095 LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
2096 return MarkAsCall(DefineFixed(
new(zone()) LFastLiteral,
rax), instr);
2100 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
2101 return MarkAsCall(DefineFixed(
new(zone()) LArrayLiteral,
rax), instr);
2105 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
2106 return MarkAsCall(DefineFixed(
new(zone()) LObjectLiteral,
rax), instr);
2110 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2111 return MarkAsCall(DefineFixed(
new(zone()) LRegExpLiteral,
rax), instr);
2115 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2116 return MarkAsCall(DefineFixed(
new(zone()) LFunctionLiteral,
rax), instr);
2120 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
2121 LOperand*
object = UseAtStart(instr->object());
2122 LOperand* key = UseOrConstantAtStart(instr->key());
2123 LDeleteProperty* result =
new(zone()) LDeleteProperty(
object, key);
2124 return MarkAsCall(DefineFixed(result,
rax), instr);
2128 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2129 ASSERT(argument_count_ == 0);
2130 allocator_->MarkAsOsrEntry();
2131 current_block_->last_environment()->set_ast_id(instr->ast_id());
2132 return AssignEnvironment(
new(zone()) LOsrEntry);
2136 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2137 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2138 return DefineAsSpilled(
new(zone()) LParameter, spill_index);
2142 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2143 int spill_index = chunk()->GetNextSpillIndex(
false);
2145 Abort(
"Too many spill slots needed for OSR");
2148 return DefineAsSpilled(
new(zone()) LUnknownOSRValue, spill_index);
2152 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2153 argument_count_ -= instr->argument_count();
2154 return MarkAsCall(DefineFixed(
new(zone()) LCallStub,
rax), instr);
2158 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2167 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2168 LOperand* args = UseRegister(instr->arguments());
2169 LOperand* length = UseTempRegister(instr->length());
2170 LOperand* index = Use(instr->index());
2171 return DefineAsRegister(
new(zone()) LAccessArgumentsAt(args, length, index));
2175 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2176 LOperand*
object = UseFixed(instr->value(),
rax);
2177 LToFastProperties* result =
new(zone()) LToFastProperties(
object);
2178 return MarkAsCall(DefineFixed(result,
rax), instr);
2182 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2183 LTypeof* result =
new(zone()) LTypeof(UseAtStart(instr->value()));
2184 return MarkAsCall(DefineFixed(result,
rax), instr);
2188 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2189 return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2193 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2194 HIsConstructCallAndBranch* instr) {
2195 return new(zone()) LIsConstructCallAndBranch(TempRegister());
2199 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2200 HEnvironment* env = current_block_->last_environment();
2203 env->set_ast_id(instr->ast_id());
2205 env->Drop(instr->pop_count());
2206 for (
int i = 0; i < instr->values()->length(); ++i) {
2207 HValue* value = instr->values()->at(i);
2208 if (instr->HasAssignedIndexAt(i)) {
2209 env->Bind(instr->GetAssignedIndexAt(i), value);
2217 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
2218 LLazyBailout* lazy_bailout =
new(zone()) LLazyBailout;
2219 LInstruction* result = AssignEnvironment(lazy_bailout);
2222 instruction_pending_deoptimization_environment_->
2223 SetDeferredLazyDeoptimizationEnvironment(result->environment());
2224 instruction_pending_deoptimization_environment_ =
NULL;
2233 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2234 if (instr->is_function_entry()) {
2235 return MarkAsCall(
new(zone()) LStackCheck, instr);
2237 ASSERT(instr->is_backwards_branch());
2238 return AssignEnvironment(AssignPointerMap(
new(zone()) LStackCheck));
2243 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2244 HEnvironment* outer = current_block_->last_environment();
2245 HConstant* undefined = graph()->GetConstantUndefined();
2246 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2247 instr->arguments_count(),
2251 instr->inlining_kind());
2252 if (instr->arguments_var() !=
NULL) {
2253 inner->Bind(instr->arguments_var(), graph()->GetArgumentsObject());
2255 inner->set_entry(instr);
2256 current_block_->UpdateEnvironment(inner);
2257 chunk_->AddInlinedClosure(instr->closure());
2262 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2263 LInstruction* pop =
NULL;
2265 HEnvironment* env = current_block_->last_environment();
2267 if (env->entry()->arguments_pushed()) {
2268 int argument_count = env->arguments_environment()->parameter_count();
2269 pop =
new(zone()) LDrop(argument_count);
2270 argument_count_ -= argument_count;
2273 HEnvironment* outer = current_block_->last_environment()->
2274 DiscardInlined(
false);
2275 current_block_->UpdateEnvironment(outer);
2281 LInstruction* LChunkBuilder::DoIn(HIn* instr) {
2282 LOperand* key = UseOrConstantAtStart(instr->key());
2283 LOperand*
object = UseOrConstantAtStart(instr->object());
2284 LIn* result =
new(zone()) LIn(key,
object);
2285 return MarkAsCall(DefineFixed(result,
rax), instr);
2289 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2290 LOperand*
object = UseFixed(instr->enumerable(),
rax);
2291 LForInPrepareMap* result =
new(zone()) LForInPrepareMap(
object);
2292 return MarkAsCall(DefineFixed(result,
rax), instr, CAN_DEOPTIMIZE_EAGERLY);
2296 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2297 LOperand* map = UseRegister(instr->map());
2298 return AssignEnvironment(DefineAsRegister(
2299 new(zone()) LForInCacheArray(map)));
2303 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2304 LOperand* value = UseRegisterAtStart(instr->value());
2305 LOperand* map = UseRegisterAtStart(instr->map());
2306 return AssignEnvironment(
new(zone()) LCheckMapValue(value, map));
2310 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2311 LOperand*
object = UseRegister(instr->object());
2312 LOperand* index = UseTempRegister(instr->index());
2313 return DefineSameAsFirst(
new(zone()) LLoadFieldByIndex(
object, index));
2319 #endif // V8_TARGET_ARCH_X64
#define DEFINE_COMPILE(type)
static LUnallocated * cast(LOperand *op)
friend class TempIterator
Handle< Map > transitioned_map()
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
Handle< Object > name() const
const char * ToCString(const v8::String::Utf8Value &value)
static String * cast(Object *obj)
virtual void PrintOutputOperandTo(StringStream *stream)
void MarkSpilledDoubleRegister(int allocation_index, LOperand *spill_operand)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
static Representation Integer32()
LLabel(HBasicBlock *block)
Handle< String > name() const
static const int kNumAllocatableRegisters
Handle< Object > name() const
LEnvironment * environment() const
#define ASSERT(condition)
virtual const char * Mnemonic() const =0
virtual void PrintDataTo(StringStream *stream)
void PrintTo(StringStream *stream)
bool IsSimpleMapChangeTransition(ElementsKind from_kind, ElementsKind to_kind)
#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
Representation representation() const
EqualityKind kind() const
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
virtual bool HasResult() const =0
virtual void PrintDataTo(StringStream *stream)
void PrintTo(StringStream *stream)
LLabel * replacement() const
static HUnaryOperation * cast(HValue *value)
virtual const char * Mnemonic() const
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
void MarkSpilledRegister(int allocation_index, LOperand *spill_operand)
static const char * String(Value tok)
static LDoubleStackSlot * Create(int index, Zone *zone)
virtual void PrintDataTo(StringStream *stream)
bool HasEnvironment() const
virtual void PrintDataTo(StringStream *stream)
virtual LOperand * result()=0
virtual void PrintDataTo(StringStream *stream)
static int ToAllocationIndex(Register reg)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
static LStackSlot * Create(int index, Zone *zone)
virtual void PrintDataTo(StringStream *stream)
static const int kMaxFixedIndex
LPointerMap * pointer_map() const
static int ToAllocationIndex(XMMRegister reg)
virtual void PrintDataTo(StringStream *stream)
virtual DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,"string-compare-and-branch") Token void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
void PrintDataTo(StringStream *stream) const
virtual const char * Mnemonic() const
static const int kNumAllocatableRegisters
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
Handle< String > name() const
virtual void PrintDataTo(StringStream *stream)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
bool HasPointerMap() const
virtual void PrintDataTo(StringStream *stream)
static HValue * cast(HValue *value)
Handle< String > type_literal()
void PrintTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
Handle< Map > original_map()
virtual void PrintDataTo(StringStream *stream)