Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(470)

Side by Side Diff: src/mips/lithium-codegen-mips.cc

Issue 142813003: A64: Synchronize with r15358. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/mips/lithium-codegen-mips.h ('k') | src/mips/lithium-mips.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 private: 55 private:
56 LCodeGen* codegen_; 56 LCodeGen* codegen_;
57 LPointerMap* pointers_; 57 LPointerMap* pointers_;
58 Safepoint::DeoptMode deopt_mode_; 58 Safepoint::DeoptMode deopt_mode_;
59 }; 59 };
60 60
61 61
62 #define __ masm()-> 62 #define __ masm()->
63 63
64 bool LCodeGen::GenerateCode() { 64 bool LCodeGen::GenerateCode() {
65 HPhase phase("Z_Code generation", chunk()); 65 LPhase phase("Z_Code generation", chunk());
66 ASSERT(is_unused()); 66 ASSERT(is_unused());
67 status_ = GENERATING; 67 status_ = GENERATING;
68 68
69 // Open a frame scope to indicate that there is a frame on the stack. The 69 // Open a frame scope to indicate that there is a frame on the stack. The
70 // NONE indicates that the scope shouldn't actually generate code to set up 70 // NONE indicates that the scope shouldn't actually generate code to set up
71 // the frame (that is done in GeneratePrologue). 71 // the frame (that is done in GeneratePrologue).
72 FrameScope frame_scope(masm_, StackFrame::NONE); 72 FrameScope frame_scope(masm_, StackFrame::NONE);
73 73
74 return GeneratePrologue() && 74 return GeneratePrologue() &&
75 GenerateBody() && 75 GenerateBody() &&
76 GenerateDeferredCode() && 76 GenerateDeferredCode() &&
77 GenerateDeoptJumpTable() && 77 GenerateDeoptJumpTable() &&
78 GenerateSafepointTable(); 78 GenerateSafepointTable();
79 } 79 }
80 80
81 81
82 void LCodeGen::FinishCode(Handle<Code> code) { 82 void LCodeGen::FinishCode(Handle<Code> code) {
83 ASSERT(is_done()); 83 ASSERT(is_done());
84 code->set_stack_slots(GetStackSlotCount()); 84 code->set_stack_slots(GetStackSlotCount());
85 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); 85 code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
86 if (FLAG_weak_embedded_maps_in_optimized_code) { 86 if (FLAG_weak_embedded_maps_in_optimized_code) {
87 RegisterDependentCodeForEmbeddedMaps(code); 87 RegisterDependentCodeForEmbeddedMaps(code);
88 } 88 }
89 PopulateDeoptimizationData(code); 89 PopulateDeoptimizationData(code);
90 info()->CommitDependentMaps(code); 90 info()->CommitDependencies(code);
91 } 91 }
92 92
93 93
94 void LChunkBuilder::Abort(const char* reason) { 94 void LChunkBuilder::Abort(const char* reason) {
95 info()->set_bailout_reason(reason); 95 info()->set_bailout_reason(reason);
96 status_ = ABORTED; 96 status_ = ABORTED;
97 } 97 }
98 98
99 99
100 void LCodeGen::Comment(const char* format, ...) { 100 void LCodeGen::Comment(const char* format, ...) {
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 cp, target.offset(), a0, a3, GetRAState(), kSaveFPRegs); 236 cp, target.offset(), a0, a3, GetRAState(), kSaveFPRegs);
237 } 237 }
238 } 238 }
239 Comment(";;; End allocate local context"); 239 Comment(";;; End allocate local context");
240 } 240 }
241 241
242 // Trace the call. 242 // Trace the call.
243 if (FLAG_trace && info()->IsOptimizing()) { 243 if (FLAG_trace && info()->IsOptimizing()) {
244 __ CallRuntime(Runtime::kTraceEnter, 0); 244 __ CallRuntime(Runtime::kTraceEnter, 0);
245 } 245 }
246 EnsureSpaceForLazyDeopt();
247 return !is_aborted(); 246 return !is_aborted();
248 } 247 }
249 248
250 249
251 bool LCodeGen::GenerateBody() { 250 bool LCodeGen::GenerateBody() {
252 ASSERT(is_generating()); 251 ASSERT(is_generating());
253 bool emit_instructions = true; 252 bool emit_instructions = true;
254 for (current_instruction_ = 0; 253 for (current_instruction_ = 0;
255 !is_aborted() && current_instruction_ < instructions_->length(); 254 !is_aborted() && current_instruction_ < instructions_->length();
256 current_instruction_++) { 255 current_instruction_++) {
257 LInstruction* instr = instructions_->at(current_instruction_); 256 LInstruction* instr = instructions_->at(current_instruction_);
258 257
259 // Don't emit code for basic blocks with a replacement. 258 // Don't emit code for basic blocks with a replacement.
260 if (instr->IsLabel()) { 259 if (instr->IsLabel()) {
261 emit_instructions = !LLabel::cast(instr)->HasReplacement(); 260 emit_instructions = !LLabel::cast(instr)->HasReplacement();
262 } 261 }
263 if (!emit_instructions) continue; 262 if (!emit_instructions) continue;
264 263
265 if (FLAG_code_comments && instr->HasInterestingComment(this)) { 264 if (FLAG_code_comments && instr->HasInterestingComment(this)) {
266 Comment(";;; <@%d,#%d> %s", 265 Comment(";;; <@%d,#%d> %s",
267 current_instruction_, 266 current_instruction_,
268 instr->hydrogen_value()->id(), 267 instr->hydrogen_value()->id(),
269 instr->Mnemonic()); 268 instr->Mnemonic());
270 } 269 }
271 270
272 instr->CompileToNative(this); 271 instr->CompileToNative(this);
273 } 272 }
273 EnsureSpaceForLazyDeopt();
274 return !is_aborted(); 274 return !is_aborted();
275 } 275 }
276 276
277 277
278 bool LCodeGen::GenerateDeferredCode() { 278 bool LCodeGen::GenerateDeferredCode() {
279 ASSERT(is_generating()); 279 ASSERT(is_generating());
280 if (deferred_.length() > 0) { 280 if (deferred_.length() > 0) {
281 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 281 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
282 LDeferredCode* code = deferred_[i]; 282 LDeferredCode* code = deferred_[i];
283 Comment(";;; <@%d,#%d> " 283 Comment(";;; <@%d,#%d> "
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 case STUB: 596 case STUB:
597 translation->BeginCompiledStubFrame(); 597 translation->BeginCompiledStubFrame();
598 break; 598 break;
599 case ARGUMENTS_ADAPTOR: 599 case ARGUMENTS_ADAPTOR:
600 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); 600 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
601 break; 601 break;
602 } 602 }
603 603
604 for (int i = 0; i < translation_size; ++i) { 604 for (int i = 0; i < translation_size; ++i) {
605 LOperand* value = environment->values()->at(i); 605 LOperand* value = environment->values()->at(i);
606 // spilled_registers_ and spilled_double_registers_ are either
607 // both NULL or both set.
608 if (environment->spilled_registers() != NULL && value != NULL) {
609 if (value->IsRegister() &&
610 environment->spilled_registers()[value->index()] != NULL) {
611 translation->MarkDuplicate();
612 AddToTranslation(translation,
613 environment->spilled_registers()[value->index()],
614 environment->HasTaggedValueAt(i),
615 environment->HasUint32ValueAt(i));
616 } else if (
617 value->IsDoubleRegister() &&
618 environment->spilled_double_registers()[value->index()] != NULL) {
619 translation->MarkDuplicate();
620 AddToTranslation(
621 translation,
622 environment->spilled_double_registers()[value->index()],
623 false,
624 false);
625 }
626 }
627 606
628 // TODO(mstarzinger): Introduce marker operands to indicate that this value 607 // TODO(mstarzinger): Introduce marker operands to indicate that this value
629 // is not present and must be reconstructed from the deoptimizer. Currently 608 // is not present and must be reconstructed from the deoptimizer. Currently
630 // this is only used for the arguments object. 609 // this is only used for the arguments object.
631 if (value == NULL) { 610 if (value == NULL) {
632 int arguments_count = environment->values()->length() - translation_size; 611 int arguments_count = environment->values()->length() - translation_size;
633 translation->BeginArgumentsObject(arguments_count); 612 translation->BeginArgumentsObject(arguments_count);
634 for (int i = 0; i < arguments_count; ++i) { 613 for (int i = 0; i < arguments_count; ++i) {
635 LOperand* value = environment->values()->at(translation_size + i); 614 LOperand* value = environment->values()->at(translation_size + i);
636 ASSERT(environment->spilled_registers() == NULL ||
637 !value->IsRegister() ||
638 environment->spilled_registers()[value->index()] == NULL);
639 ASSERT(environment->spilled_registers() == NULL ||
640 !value->IsDoubleRegister() ||
641 environment->spilled_double_registers()[value->index()] == NULL);
642 AddToTranslation(translation, 615 AddToTranslation(translation,
643 value, 616 value,
644 environment->HasTaggedValueAt(translation_size + i), 617 environment->HasTaggedValueAt(translation_size + i),
645 environment->HasUint32ValueAt(translation_size + i)); 618 environment->HasUint32ValueAt(translation_size + i));
646 } 619 }
647 continue; 620 continue;
648 } 621 }
649 622
650 AddToTranslation(translation, 623 AddToTranslation(translation,
651 value, 624 value,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 RelocInfo::Mode mode, 672 RelocInfo::Mode mode,
700 LInstruction* instr) { 673 LInstruction* instr) {
701 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); 674 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
702 } 675 }
703 676
704 677
705 void LCodeGen::CallCodeGeneric(Handle<Code> code, 678 void LCodeGen::CallCodeGeneric(Handle<Code> code,
706 RelocInfo::Mode mode, 679 RelocInfo::Mode mode,
707 LInstruction* instr, 680 LInstruction* instr,
708 SafepointMode safepoint_mode) { 681 SafepointMode safepoint_mode) {
682 EnsureSpaceForLazyDeopt();
709 ASSERT(instr != NULL); 683 ASSERT(instr != NULL);
710 LPointerMap* pointers = instr->pointer_map(); 684 LPointerMap* pointers = instr->pointer_map();
711 RecordPosition(pointers->position()); 685 RecordPosition(pointers->position());
712 __ Call(code, mode); 686 __ Call(code, mode);
713 RecordSafepointWithLazyDeopt(instr, safepoint_mode); 687 RecordSafepointWithLazyDeopt(instr, safepoint_mode);
714 } 688 }
715 689
716 690
717 void LCodeGen::CallRuntime(const Runtime::Function* function, 691 void LCodeGen::CallRuntime(const Runtime::Function* function,
718 int num_arguments, 692 int num_arguments,
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 1067 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
1094 break; 1068 break;
1095 } 1069 }
1096 default: 1070 default:
1097 UNREACHABLE(); 1071 UNREACHABLE();
1098 } 1072 }
1099 } 1073 }
1100 1074
1101 1075
1102 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 1076 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
1103 // Nothing to do. 1077 // Record the address of the first unknown OSR value as the place to enter.
1078 if (osr_pc_offset_ == -1) osr_pc_offset_ = masm()->pc_offset();
1104 } 1079 }
1105 1080
1106 1081
1107 void LCodeGen::DoModI(LModI* instr) { 1082 void LCodeGen::DoModI(LModI* instr) {
1108 HMod* hmod = instr->hydrogen(); 1083 HMod* hmod = instr->hydrogen();
1109 HValue* left = hmod->left(); 1084 HValue* left = hmod->left();
1110 HValue* right = hmod->right(); 1085 HValue* right = hmod->right();
1111 if (hmod->HasPowerOf2Divisor()) { 1086 if (hmod->HasPowerOf2Divisor()) {
1112 const Register scratch = scratch0(); 1087 const Register scratch = scratch0();
1113 const Register left_reg = ToRegister(instr->left()); 1088 const Register left_reg = ToRegister(instr->left());
(...skipping 15 matching lines...) Expand all
1129 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg)); 1104 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg));
1130 } 1105 }
1131 __ Branch(USE_DELAY_SLOT, &done); 1106 __ Branch(USE_DELAY_SLOT, &done);
1132 __ subu(result_reg, zero_reg, result_reg); 1107 __ subu(result_reg, zero_reg, result_reg);
1133 } 1108 }
1134 1109
1135 __ bind(&left_is_not_negative); 1110 __ bind(&left_is_not_negative);
1136 __ And(result_reg, scratch, divisor - 1); 1111 __ And(result_reg, scratch, divisor - 1);
1137 __ bind(&done); 1112 __ bind(&done);
1138 1113
1139 } else { 1114 } else if (hmod->fixed_right_arg().has_value) {
1140 // TODO(svenpanne) Add right->has_fixed_right_arg() case.
1141
1142 const Register scratch = scratch0(); 1115 const Register scratch = scratch0();
1143 const Register left_reg = ToRegister(instr->left()); 1116 const Register left_reg = ToRegister(instr->left());
1144 const Register result_reg = ToRegister(instr->result()); 1117 const Register result_reg = ToRegister(instr->result());
1118
1119 Register right_reg = EmitLoadRegister(instr->right(), scratch);
1120
1121 int32_t divisor = hmod->fixed_right_arg().value;
1122 ASSERT(IsPowerOf2(divisor));
1123
1124 // Check if our assumption of a fixed right operand still holds.
1125 DeoptimizeIf(ne, instr->environment(), right_reg, Operand(divisor));
1126
1127 Label left_is_not_negative, done;
1128 if (left->CanBeNegative()) {
1129 __ Branch(USE_DELAY_SLOT, &left_is_not_negative,
1130 ge, left_reg, Operand(zero_reg));
1131 __ subu(result_reg, zero_reg, left_reg);
1132 __ And(result_reg, result_reg, divisor - 1);
1133 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1134 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg));
1135 }
1136 __ Branch(USE_DELAY_SLOT, &done);
1137 __ subu(result_reg, zero_reg, result_reg);
1138 }
1139
1140 __ bind(&left_is_not_negative);
1141 __ And(result_reg, left_reg, divisor - 1);
1142 __ bind(&done);
1143
1144 } else {
1145 const Register scratch = scratch0();
1146 const Register left_reg = ToRegister(instr->left());
1147 const Register result_reg = ToRegister(instr->result());
1145 1148
1146 // div runs in the background while we check for special cases. 1149 // div runs in the background while we check for special cases.
1147 Register right_reg = EmitLoadRegister(instr->right(), scratch); 1150 Register right_reg = EmitLoadRegister(instr->right(), scratch);
1148 __ div(left_reg, right_reg); 1151 __ div(left_reg, right_reg);
1149 1152
1150 Label done; 1153 Label done;
1151 // Check for x % 0, we have to deopt in this case because we can't return a 1154 // Check for x % 0, we have to deopt in this case because we can't return a
1152 // NaN. 1155 // NaN.
1153 if (right->CanBeZero()) { 1156 if (right->CanBeZero()) {
1154 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(zero_reg)); 1157 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(zero_reg));
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after
1699 __ Ext(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); 1702 __ Ext(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount);
1700 } 1703 }
1701 1704
1702 1705
1703 void LCodeGen::DoValueOf(LValueOf* instr) { 1706 void LCodeGen::DoValueOf(LValueOf* instr) {
1704 Register input = ToRegister(instr->value()); 1707 Register input = ToRegister(instr->value());
1705 Register result = ToRegister(instr->result()); 1708 Register result = ToRegister(instr->result());
1706 Register map = ToRegister(instr->temp()); 1709 Register map = ToRegister(instr->temp());
1707 Label done; 1710 Label done;
1708 1711
1709 // If the object is a smi return the object. 1712 if (!instr->hydrogen()->value()->IsHeapObject()) {
1710 __ Move(result, input); 1713 // If the object is a smi return the object.
1711 __ JumpIfSmi(input, &done); 1714 __ Move(result, input);
1715 __ JumpIfSmi(input, &done);
1716 }
1712 1717
1713 // If the object is not a value type, return the object. 1718 // If the object is not a value type, return the object.
1714 __ GetObjectType(input, map, map); 1719 __ GetObjectType(input, map, map);
1715 __ Branch(&done, ne, map, Operand(JS_VALUE_TYPE)); 1720 __ Branch(&done, ne, map, Operand(JS_VALUE_TYPE));
1716 __ lw(result, FieldMemOperand(input, JSValue::kValueOffset)); 1721 __ lw(result, FieldMemOperand(input, JSValue::kValueOffset));
1717 1722
1718 __ bind(&done); 1723 __ bind(&done);
1719 } 1724 }
1720 1725
1721 1726
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
1963 } 1968 }
1964 1969
1965 1970
1966 int LCodeGen::GetNextEmittedBlock() const { 1971 int LCodeGen::GetNextEmittedBlock() const {
1967 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { 1972 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) {
1968 if (!chunk_->GetLabel(i)->HasReplacement()) return i; 1973 if (!chunk_->GetLabel(i)->HasReplacement()) return i;
1969 } 1974 }
1970 return -1; 1975 return -1;
1971 } 1976 }
1972 1977
1978 template<class InstrType>
1979 void LCodeGen::EmitBranch(InstrType instr,
1980 Condition cc, Register src1, const Operand& src2) {
1981 int right_block = instr->FalseDestination(chunk_);
1982 int left_block = instr->TrueDestination(chunk_);
1973 1983
1974 void LCodeGen::EmitBranch(int left_block, int right_block,
1975 Condition cc, Register src1, const Operand& src2) {
1976 int next_block = GetNextEmittedBlock(); 1984 int next_block = GetNextEmittedBlock();
1977 right_block = chunk_->LookupDestination(right_block);
1978 left_block = chunk_->LookupDestination(left_block);
1979 if (right_block == left_block) { 1985 if (right_block == left_block) {
1980 EmitGoto(left_block); 1986 EmitGoto(left_block);
1981 } else if (left_block == next_block) { 1987 } else if (left_block == next_block) {
1982 __ Branch(chunk_->GetAssemblyLabel(right_block), 1988 __ Branch(chunk_->GetAssemblyLabel(right_block),
1983 NegateCondition(cc), src1, src2); 1989 NegateCondition(cc), src1, src2);
1984 } else if (right_block == next_block) { 1990 } else if (right_block == next_block) {
1985 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2); 1991 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2);
1986 } else { 1992 } else {
1987 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2); 1993 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2);
1988 __ Branch(chunk_->GetAssemblyLabel(right_block)); 1994 __ Branch(chunk_->GetAssemblyLabel(right_block));
1989 } 1995 }
1990 } 1996 }
1991 1997
1992 1998
1993 void LCodeGen::EmitBranchF(int left_block, int right_block, 1999 template<class InstrType>
2000 void LCodeGen::EmitBranchF(InstrType instr,
1994 Condition cc, FPURegister src1, FPURegister src2) { 2001 Condition cc, FPURegister src1, FPURegister src2) {
2002 int right_block = instr->FalseDestination(chunk_);
2003 int left_block = instr->TrueDestination(chunk_);
2004
1995 int next_block = GetNextEmittedBlock(); 2005 int next_block = GetNextEmittedBlock();
1996 right_block = chunk_->LookupDestination(right_block);
1997 left_block = chunk_->LookupDestination(left_block);
1998 if (right_block == left_block) { 2006 if (right_block == left_block) {
1999 EmitGoto(left_block); 2007 EmitGoto(left_block);
2000 } else if (left_block == next_block) { 2008 } else if (left_block == next_block) {
2001 __ BranchF(chunk_->GetAssemblyLabel(right_block), NULL, 2009 __ BranchF(chunk_->GetAssemblyLabel(right_block), NULL,
2002 NegateCondition(cc), src1, src2); 2010 NegateCondition(cc), src1, src2);
2003 } else if (right_block == next_block) { 2011 } else if (right_block == next_block) {
2004 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, cc, src1, src2); 2012 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, cc, src1, src2);
2005 } else { 2013 } else {
2006 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, cc, src1, src2); 2014 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, cc, src1, src2);
2007 __ Branch(chunk_->GetAssemblyLabel(right_block)); 2015 __ Branch(chunk_->GetAssemblyLabel(right_block));
2008 } 2016 }
2009 } 2017 }
2010 2018
2011 2019
2012 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { 2020 void LCodeGen::DoDebugBreak(LDebugBreak* instr) {
2013 __ stop("LDebugBreak"); 2021 __ stop("LDebugBreak");
2014 } 2022 }
2015 2023
2016 2024
2017 void LCodeGen::DoBranch(LBranch* instr) { 2025 void LCodeGen::DoBranch(LBranch* instr) {
2018 int true_block = chunk_->LookupDestination(instr->true_block_id());
2019 int false_block = chunk_->LookupDestination(instr->false_block_id());
2020
2021 Representation r = instr->hydrogen()->value()->representation(); 2026 Representation r = instr->hydrogen()->value()->representation();
2022 if (r.IsInteger32() || r.IsSmi()) { 2027 if (r.IsInteger32() || r.IsSmi()) {
2023 ASSERT(!info()->IsStub()); 2028 ASSERT(!info()->IsStub());
2024 Register reg = ToRegister(instr->value()); 2029 Register reg = ToRegister(instr->value());
2025 EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg)); 2030 EmitBranch(instr, ne, reg, Operand(zero_reg));
2026 } else if (r.IsDouble()) { 2031 } else if (r.IsDouble()) {
2027 ASSERT(!info()->IsStub()); 2032 ASSERT(!info()->IsStub());
2028 DoubleRegister reg = ToDoubleRegister(instr->value()); 2033 DoubleRegister reg = ToDoubleRegister(instr->value());
2029 // Test the double value. Zero and NaN are false. 2034 // Test the double value. Zero and NaN are false.
2030 EmitBranchF(true_block, false_block, nue, reg, kDoubleRegZero); 2035 EmitBranchF(instr, nue, reg, kDoubleRegZero);
2031 } else { 2036 } else {
2032 ASSERT(r.IsTagged()); 2037 ASSERT(r.IsTagged());
2033 Register reg = ToRegister(instr->value()); 2038 Register reg = ToRegister(instr->value());
2034 HType type = instr->hydrogen()->value()->type(); 2039 HType type = instr->hydrogen()->value()->type();
2035 if (type.IsBoolean()) { 2040 if (type.IsBoolean()) {
2036 ASSERT(!info()->IsStub()); 2041 ASSERT(!info()->IsStub());
2037 __ LoadRoot(at, Heap::kTrueValueRootIndex); 2042 __ LoadRoot(at, Heap::kTrueValueRootIndex);
2038 EmitBranch(true_block, false_block, eq, reg, Operand(at)); 2043 EmitBranch(instr, eq, reg, Operand(at));
2039 } else if (type.IsSmi()) { 2044 } else if (type.IsSmi()) {
2040 ASSERT(!info()->IsStub()); 2045 ASSERT(!info()->IsStub());
2041 EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg)); 2046 EmitBranch(instr, ne, reg, Operand(zero_reg));
2047 } else if (type.IsJSArray()) {
2048 ASSERT(!info()->IsStub());
2049 EmitBranch(instr, al, zero_reg, Operand(zero_reg));
2050 } else if (type.IsHeapNumber()) {
2051 ASSERT(!info()->IsStub());
2052 DoubleRegister dbl_scratch = double_scratch0();
2053 __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
2054 // Test the double value. Zero and NaN are false.
2055 EmitBranchF(instr, nue, dbl_scratch, kDoubleRegZero);
2056 } else if (type.IsString()) {
2057 ASSERT(!info()->IsStub());
2058 __ lw(at, FieldMemOperand(reg, String::kLengthOffset));
2059 EmitBranch(instr, ne, at, Operand(zero_reg));
2042 } else { 2060 } else {
2043 Label* true_label = chunk_->GetAssemblyLabel(true_block);
2044 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2045
2046 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); 2061 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
2047 // Avoid deopts in the case where we've never executed this path before. 2062 // Avoid deopts in the case where we've never executed this path before.
2048 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); 2063 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
2049 2064
2050 if (expected.Contains(ToBooleanStub::UNDEFINED)) { 2065 if (expected.Contains(ToBooleanStub::UNDEFINED)) {
2051 // undefined -> false. 2066 // undefined -> false.
2052 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 2067 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
2053 __ Branch(false_label, eq, reg, Operand(at)); 2068 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at));
2054 } 2069 }
2055 if (expected.Contains(ToBooleanStub::BOOLEAN)) { 2070 if (expected.Contains(ToBooleanStub::BOOLEAN)) {
2056 // Boolean -> its value. 2071 // Boolean -> its value.
2057 __ LoadRoot(at, Heap::kTrueValueRootIndex); 2072 __ LoadRoot(at, Heap::kTrueValueRootIndex);
2058 __ Branch(true_label, eq, reg, Operand(at)); 2073 __ Branch(instr->TrueLabel(chunk_), eq, reg, Operand(at));
2059 __ LoadRoot(at, Heap::kFalseValueRootIndex); 2074 __ LoadRoot(at, Heap::kFalseValueRootIndex);
2060 __ Branch(false_label, eq, reg, Operand(at)); 2075 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at));
2061 } 2076 }
2062 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { 2077 if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
2063 // 'null' -> false. 2078 // 'null' -> false.
2064 __ LoadRoot(at, Heap::kNullValueRootIndex); 2079 __ LoadRoot(at, Heap::kNullValueRootIndex);
2065 __ Branch(false_label, eq, reg, Operand(at)); 2080 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at));
2066 } 2081 }
2067 2082
2068 if (expected.Contains(ToBooleanStub::SMI)) { 2083 if (expected.Contains(ToBooleanStub::SMI)) {
2069 // Smis: 0 -> false, all other -> true. 2084 // Smis: 0 -> false, all other -> true.
2070 __ Branch(false_label, eq, reg, Operand(zero_reg)); 2085 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(zero_reg));
2071 __ JumpIfSmi(reg, true_label); 2086 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2072 } else if (expected.NeedsMap()) { 2087 } else if (expected.NeedsMap()) {
2073 // If we need a map later and have a Smi -> deopt. 2088 // If we need a map later and have a Smi -> deopt.
2074 __ And(at, reg, Operand(kSmiTagMask)); 2089 __ And(at, reg, Operand(kSmiTagMask));
2075 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); 2090 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg));
2076 } 2091 }
2077 2092
2078 const Register map = scratch0(); 2093 const Register map = scratch0();
2079 if (expected.NeedsMap()) { 2094 if (expected.NeedsMap()) {
2080 __ lw(map, FieldMemOperand(reg, HeapObject::kMapOffset)); 2095 __ lw(map, FieldMemOperand(reg, HeapObject::kMapOffset));
2081 if (expected.CanBeUndetectable()) { 2096 if (expected.CanBeUndetectable()) {
2082 // Undetectable -> false. 2097 // Undetectable -> false.
2083 __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset)); 2098 __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset));
2084 __ And(at, at, Operand(1 << Map::kIsUndetectable)); 2099 __ And(at, at, Operand(1 << Map::kIsUndetectable));
2085 __ Branch(false_label, ne, at, Operand(zero_reg)); 2100 __ Branch(instr->FalseLabel(chunk_), ne, at, Operand(zero_reg));
2086 } 2101 }
2087 } 2102 }
2088 2103
2089 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { 2104 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
2090 // spec object -> true. 2105 // spec object -> true.
2091 __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset)); 2106 __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
2092 __ Branch(true_label, ge, at, Operand(FIRST_SPEC_OBJECT_TYPE)); 2107 __ Branch(instr->TrueLabel(chunk_),
2108 ge, at, Operand(FIRST_SPEC_OBJECT_TYPE));
2093 } 2109 }
2094 2110
2095 if (expected.Contains(ToBooleanStub::STRING)) { 2111 if (expected.Contains(ToBooleanStub::STRING)) {
2096 // String value -> false iff empty. 2112 // String value -> false iff empty.
2097 Label not_string; 2113 Label not_string;
2098 __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset)); 2114 __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
2099 __ Branch(&not_string, ge , at, Operand(FIRST_NONSTRING_TYPE)); 2115 __ Branch(&not_string, ge , at, Operand(FIRST_NONSTRING_TYPE));
2100 __ lw(at, FieldMemOperand(reg, String::kLengthOffset)); 2116 __ lw(at, FieldMemOperand(reg, String::kLengthOffset));
2101 __ Branch(true_label, ne, at, Operand(zero_reg)); 2117 __ Branch(instr->TrueLabel(chunk_), ne, at, Operand(zero_reg));
2102 __ Branch(false_label); 2118 __ Branch(instr->FalseLabel(chunk_));
2103 __ bind(&not_string); 2119 __ bind(&not_string);
2104 } 2120 }
2105 2121
2106 if (expected.Contains(ToBooleanStub::SYMBOL)) { 2122 if (expected.Contains(ToBooleanStub::SYMBOL)) {
2107 // Symbol value -> true. 2123 // Symbol value -> true.
2108 const Register scratch = scratch1(); 2124 const Register scratch = scratch1();
2109 __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); 2125 __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
2110 __ Branch(true_label, eq, scratch, Operand(SYMBOL_TYPE)); 2126 __ Branch(instr->TrueLabel(chunk_), eq, scratch, Operand(SYMBOL_TYPE));
2111 } 2127 }
2112 2128
2113 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { 2129 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
2114 // heap number -> false iff +0, -0, or NaN. 2130 // heap number -> false iff +0, -0, or NaN.
2115 DoubleRegister dbl_scratch = double_scratch0(); 2131 DoubleRegister dbl_scratch = double_scratch0();
2116 Label not_heap_number; 2132 Label not_heap_number;
2117 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); 2133 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
2118 __ Branch(&not_heap_number, ne, map, Operand(at)); 2134 __ Branch(&not_heap_number, ne, map, Operand(at));
2119 __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); 2135 __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
2120 __ BranchF(true_label, false_label, ne, dbl_scratch, kDoubleRegZero); 2136 __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2137 ne, dbl_scratch, kDoubleRegZero);
2121 // Falls through if dbl_scratch == 0. 2138 // Falls through if dbl_scratch == 0.
2122 __ Branch(false_label); 2139 __ Branch(instr->FalseLabel(chunk_));
2123 __ bind(&not_heap_number); 2140 __ bind(&not_heap_number);
2124 } 2141 }
2125 2142
2126 // We've seen something for the first time -> deopt. 2143 if (!expected.IsGeneric()) {
2127 DeoptimizeIf(al, instr->environment(), zero_reg, Operand(zero_reg)); 2144 // We've seen something for the first time -> deopt.
2145 // This can only happen if we are not generic already.
2146 DeoptimizeIf(al, instr->environment(), zero_reg, Operand(zero_reg));
2147 }
2128 } 2148 }
2129 } 2149 }
2130 } 2150 }
2131 2151
2132 2152
2133 void LCodeGen::EmitGoto(int block) { 2153 void LCodeGen::EmitGoto(int block) {
2134 if (!IsNextEmittedBlock(block)) { 2154 if (!IsNextEmittedBlock(block)) {
2135 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); 2155 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2136 } 2156 }
2137 } 2157 }
2138 2158
2139 2159
2140 void LCodeGen::DoGoto(LGoto* instr) { 2160 void LCodeGen::DoGoto(LGoto* instr) {
2141 EmitGoto(instr->block_id()); 2161 EmitGoto(instr->block_id());
2142 } 2162 }
2143 2163
2144 2164
2145 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { 2165 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
(...skipping 20 matching lines...) Expand all
2166 default: 2186 default:
2167 UNREACHABLE(); 2187 UNREACHABLE();
2168 } 2188 }
2169 return cond; 2189 return cond;
2170 } 2190 }
2171 2191
2172 2192
2173 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 2193 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
2174 LOperand* left = instr->left(); 2194 LOperand* left = instr->left();
2175 LOperand* right = instr->right(); 2195 LOperand* right = instr->right();
2176 int false_block = chunk_->LookupDestination(instr->false_block_id());
2177 int true_block = chunk_->LookupDestination(instr->true_block_id());
2178
2179 Condition cond = TokenToCondition(instr->op(), false); 2196 Condition cond = TokenToCondition(instr->op(), false);
2180 2197
2181 if (left->IsConstantOperand() && right->IsConstantOperand()) { 2198 if (left->IsConstantOperand() && right->IsConstantOperand()) {
2182 // We can statically evaluate the comparison. 2199 // We can statically evaluate the comparison.
2183 double left_val = ToDouble(LConstantOperand::cast(left)); 2200 double left_val = ToDouble(LConstantOperand::cast(left));
2184 double right_val = ToDouble(LConstantOperand::cast(right)); 2201 double right_val = ToDouble(LConstantOperand::cast(right));
2185 int next_block = 2202 int next_block = EvalComparison(instr->op(), left_val, right_val) ?
2186 EvalComparison(instr->op(), left_val, right_val) ? true_block 2203 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_);
2187 : false_block;
2188 EmitGoto(next_block); 2204 EmitGoto(next_block);
2189 } else { 2205 } else {
2190 if (instr->is_double()) { 2206 if (instr->is_double()) {
2191 // Compare left and right as doubles and load the 2207 // Compare left and right as doubles and load the
2192 // resulting flags into the normal status register. 2208 // resulting flags into the normal status register.
2193 FPURegister left_reg = ToDoubleRegister(left); 2209 FPURegister left_reg = ToDoubleRegister(left);
2194 FPURegister right_reg = ToDoubleRegister(right); 2210 FPURegister right_reg = ToDoubleRegister(right);
2195 2211
2196 // If a NaN is involved, i.e. the result is unordered, 2212 // If a NaN is involved, i.e. the result is unordered,
2197 // jump to false block label. 2213 // jump to false block label.
2198 __ BranchF(NULL, chunk_->GetAssemblyLabel(false_block), eq, 2214 __ BranchF(NULL, instr->FalseLabel(chunk_), eq,
2199 left_reg, right_reg); 2215 left_reg, right_reg);
2200 2216
2201 EmitBranchF(true_block, false_block, cond, left_reg, right_reg); 2217 EmitBranchF(instr, cond, left_reg, right_reg);
2202 } else { 2218 } else {
2203 Register cmp_left; 2219 Register cmp_left;
2204 Operand cmp_right = Operand(0); 2220 Operand cmp_right = Operand(0);
2205 2221
2206 if (right->IsConstantOperand()) { 2222 if (right->IsConstantOperand()) {
2207 int32_t value = ToInteger32(LConstantOperand::cast(right)); 2223 int32_t value = ToInteger32(LConstantOperand::cast(right));
2208 if (instr->hydrogen_value()->representation().IsSmi()) { 2224 if (instr->hydrogen_value()->representation().IsSmi()) {
2209 cmp_left = ToRegister(left); 2225 cmp_left = ToRegister(left);
2210 cmp_right = Operand(Smi::FromInt(value)); 2226 cmp_right = Operand(Smi::FromInt(value));
2211 } else { 2227 } else {
2212 cmp_left = ToRegister(left); 2228 cmp_left = ToRegister(left);
2213 cmp_right = Operand(value); 2229 cmp_right = Operand(value);
2214 } 2230 }
2215 } else if (left->IsConstantOperand()) { 2231 } else if (left->IsConstantOperand()) {
2216 int32_t value = ToInteger32(LConstantOperand::cast(left)); 2232 int32_t value = ToInteger32(LConstantOperand::cast(left));
2217 if (instr->hydrogen_value()->representation().IsSmi()) { 2233 if (instr->hydrogen_value()->representation().IsSmi()) {
2218 cmp_left = ToRegister(right); 2234 cmp_left = ToRegister(right);
2219 cmp_right = Operand(Smi::FromInt(value)); 2235 cmp_right = Operand(Smi::FromInt(value));
2220 } else { 2236 } else {
2221 cmp_left = ToRegister(right); 2237 cmp_left = ToRegister(right);
2222 cmp_right = Operand(value); 2238 cmp_right = Operand(value);
2223 } 2239 }
2224 // We transposed the operands. Reverse the condition. 2240 // We transposed the operands. Reverse the condition.
2225 cond = ReverseCondition(cond); 2241 cond = ReverseCondition(cond);
2226 } else { 2242 } else {
2227 cmp_left = ToRegister(left); 2243 cmp_left = ToRegister(left);
2228 cmp_right = Operand(ToRegister(right)); 2244 cmp_right = Operand(ToRegister(right));
2229 } 2245 }
2230 2246
2231 EmitBranch(true_block, false_block, cond, cmp_left, cmp_right); 2247 EmitBranch(instr, cond, cmp_left, cmp_right);
2232 } 2248 }
2233 } 2249 }
2234 } 2250 }
2235 2251
2236 2252
2237 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { 2253 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
2238 Register left = ToRegister(instr->left()); 2254 Register left = ToRegister(instr->left());
2239 Register right = ToRegister(instr->right()); 2255 Register right = ToRegister(instr->right());
2240 int false_block = chunk_->LookupDestination(instr->false_block_id());
2241 int true_block = chunk_->LookupDestination(instr->true_block_id());
2242 2256
2243 EmitBranch(true_block, false_block, eq, left, Operand(right)); 2257 EmitBranch(instr, eq, left, Operand(right));
2244 } 2258 }
2245 2259
2246 2260
2247 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { 2261 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) {
2248 Register left = ToRegister(instr->left()); 2262 Register left = ToRegister(instr->left());
2249 int true_block = chunk_->LookupDestination(instr->true_block_id());
2250 int false_block = chunk_->LookupDestination(instr->false_block_id());
2251 2263
2252 EmitBranch(true_block, false_block, eq, left, 2264 EmitBranch(instr, eq, left, Operand(instr->hydrogen()->right()));
2253 Operand(instr->hydrogen()->right()));
2254 } 2265 }
2255 2266
2256 2267
2257 Condition LCodeGen::EmitIsObject(Register input, 2268 Condition LCodeGen::EmitIsObject(Register input,
2258 Register temp1, 2269 Register temp1,
2259 Register temp2, 2270 Register temp2,
2260 Label* is_not_object, 2271 Label* is_not_object,
2261 Label* is_object) { 2272 Label* is_object) {
2262 __ JumpIfSmi(input, is_not_object); 2273 __ JumpIfSmi(input, is_not_object);
2263 2274
(...skipping 14 matching lines...) Expand all
2278 2289
2279 return le; 2290 return le;
2280 } 2291 }
2281 2292
2282 2293
2283 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { 2294 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
2284 Register reg = ToRegister(instr->value()); 2295 Register reg = ToRegister(instr->value());
2285 Register temp1 = ToRegister(instr->temp()); 2296 Register temp1 = ToRegister(instr->temp());
2286 Register temp2 = scratch0(); 2297 Register temp2 = scratch0();
2287 2298
2288 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2299 Condition true_cond =
2289 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2300 EmitIsObject(reg, temp1, temp2,
2290 Label* true_label = chunk_->GetAssemblyLabel(true_block); 2301 instr->FalseLabel(chunk_), instr->TrueLabel(chunk_));
2291 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2292 2302
2293 Condition true_cond = 2303 EmitBranch(instr, true_cond, temp2,
2294 EmitIsObject(reg, temp1, temp2, false_label, true_label);
2295
2296 EmitBranch(true_block, false_block, true_cond, temp2,
2297 Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2304 Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
2298 } 2305 }
2299 2306
2300 2307
2301 Condition LCodeGen::EmitIsString(Register input, 2308 Condition LCodeGen::EmitIsString(Register input,
2302 Register temp1, 2309 Register temp1,
2303 Label* is_not_string) { 2310 Label* is_not_string,
2304 __ JumpIfSmi(input, is_not_string); 2311 SmiCheck check_needed = INLINE_SMI_CHECK) {
2312 if (check_needed == INLINE_SMI_CHECK) {
2313 __ JumpIfSmi(input, is_not_string);
2314 }
2305 __ GetObjectType(input, temp1, temp1); 2315 __ GetObjectType(input, temp1, temp1);
2306 2316
2307 return lt; 2317 return lt;
2308 } 2318 }
2309 2319
2310 2320
2311 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { 2321 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
2312 Register reg = ToRegister(instr->value()); 2322 Register reg = ToRegister(instr->value());
2313 Register temp1 = ToRegister(instr->temp()); 2323 Register temp1 = ToRegister(instr->temp());
2314 2324
2315 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2325 SmiCheck check_needed =
2316 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2326 instr->hydrogen()->value()->IsHeapObject()
2317 Label* false_label = chunk_->GetAssemblyLabel(false_block); 2327 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2328 Condition true_cond =
2329 EmitIsString(reg, temp1, instr->FalseLabel(chunk_), check_needed);
2318 2330
2319 Condition true_cond = 2331 EmitBranch(instr, true_cond, temp1,
2320 EmitIsString(reg, temp1, false_label);
2321
2322 EmitBranch(true_block, false_block, true_cond, temp1,
2323 Operand(FIRST_NONSTRING_TYPE)); 2332 Operand(FIRST_NONSTRING_TYPE));
2324 } 2333 }
2325 2334
2326 2335
2327 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 2336 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
2328 int true_block = chunk_->LookupDestination(instr->true_block_id());
2329 int false_block = chunk_->LookupDestination(instr->false_block_id());
2330
2331 Register input_reg = EmitLoadRegister(instr->value(), at); 2337 Register input_reg = EmitLoadRegister(instr->value(), at);
2332 __ And(at, input_reg, kSmiTagMask); 2338 __ And(at, input_reg, kSmiTagMask);
2333 EmitBranch(true_block, false_block, eq, at, Operand(zero_reg)); 2339 EmitBranch(instr, eq, at, Operand(zero_reg));
2334 } 2340 }
2335 2341
2336 2342
2337 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { 2343 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
2338 Register input = ToRegister(instr->value()); 2344 Register input = ToRegister(instr->value());
2339 Register temp = ToRegister(instr->temp()); 2345 Register temp = ToRegister(instr->temp());
2340 2346
2341 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2347 if (!instr->hydrogen()->value()->IsHeapObject()) {
2342 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2348 __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2343 2349 }
2344 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block));
2345 __ lw(temp, FieldMemOperand(input, HeapObject::kMapOffset)); 2350 __ lw(temp, FieldMemOperand(input, HeapObject::kMapOffset));
2346 __ lbu(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); 2351 __ lbu(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
2347 __ And(at, temp, Operand(1 << Map::kIsUndetectable)); 2352 __ And(at, temp, Operand(1 << Map::kIsUndetectable));
2348 EmitBranch(true_block, false_block, ne, at, Operand(zero_reg)); 2353 EmitBranch(instr, ne, at, Operand(zero_reg));
2349 } 2354 }
2350 2355
2351 2356
2352 static Condition ComputeCompareCondition(Token::Value op) { 2357 static Condition ComputeCompareCondition(Token::Value op) {
2353 switch (op) { 2358 switch (op) {
2354 case Token::EQ_STRICT: 2359 case Token::EQ_STRICT:
2355 case Token::EQ: 2360 case Token::EQ:
2356 return eq; 2361 return eq;
2357 case Token::LT: 2362 case Token::LT:
2358 return lt; 2363 return lt;
2359 case Token::GT: 2364 case Token::GT:
2360 return gt; 2365 return gt;
2361 case Token::LTE: 2366 case Token::LTE:
2362 return le; 2367 return le;
2363 case Token::GTE: 2368 case Token::GTE:
2364 return ge; 2369 return ge;
2365 default: 2370 default:
2366 UNREACHABLE(); 2371 UNREACHABLE();
2367 return kNoCondition; 2372 return kNoCondition;
2368 } 2373 }
2369 } 2374 }
2370 2375
2371 2376
2372 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { 2377 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
2373 Token::Value op = instr->op(); 2378 Token::Value op = instr->op();
2374 int true_block = chunk_->LookupDestination(instr->true_block_id());
2375 int false_block = chunk_->LookupDestination(instr->false_block_id());
2376 2379
2377 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); 2380 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
2378 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2381 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2379 2382
2380 Condition condition = ComputeCompareCondition(op); 2383 Condition condition = ComputeCompareCondition(op);
2381 2384
2382 EmitBranch(true_block, false_block, condition, v0, Operand(zero_reg)); 2385 EmitBranch(instr, condition, v0, Operand(zero_reg));
2383 } 2386 }
2384 2387
2385 2388
2386 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { 2389 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
2387 InstanceType from = instr->from(); 2390 InstanceType from = instr->from();
2388 InstanceType to = instr->to(); 2391 InstanceType to = instr->to();
2389 if (from == FIRST_TYPE) return to; 2392 if (from == FIRST_TYPE) return to;
2390 ASSERT(from == to || to == LAST_TYPE); 2393 ASSERT(from == to || to == LAST_TYPE);
2391 return from; 2394 return from;
2392 } 2395 }
2393 2396
2394 2397
2395 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { 2398 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
2396 InstanceType from = instr->from(); 2399 InstanceType from = instr->from();
2397 InstanceType to = instr->to(); 2400 InstanceType to = instr->to();
2398 if (from == to) return eq; 2401 if (from == to) return eq;
2399 if (to == LAST_TYPE) return hs; 2402 if (to == LAST_TYPE) return hs;
2400 if (from == FIRST_TYPE) return ls; 2403 if (from == FIRST_TYPE) return ls;
2401 UNREACHABLE(); 2404 UNREACHABLE();
2402 return eq; 2405 return eq;
2403 } 2406 }
2404 2407
2405 2408
2406 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 2409 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
2407 Register scratch = scratch0(); 2410 Register scratch = scratch0();
2408 Register input = ToRegister(instr->value()); 2411 Register input = ToRegister(instr->value());
2409 2412
2410 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2413 if (!instr->hydrogen()->value()->IsHeapObject()) {
2411 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2414 __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2412 2415 }
2413 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2414
2415 __ JumpIfSmi(input, false_label);
2416 2416
2417 __ GetObjectType(input, scratch, scratch); 2417 __ GetObjectType(input, scratch, scratch);
2418 EmitBranch(true_block, 2418 EmitBranch(instr,
2419 false_block,
2420 BranchCondition(instr->hydrogen()), 2419 BranchCondition(instr->hydrogen()),
2421 scratch, 2420 scratch,
2422 Operand(TestType(instr->hydrogen()))); 2421 Operand(TestType(instr->hydrogen())));
2423 } 2422 }
2424 2423
2425 2424
2426 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { 2425 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
2427 Register input = ToRegister(instr->value()); 2426 Register input = ToRegister(instr->value());
2428 Register result = ToRegister(instr->result()); 2427 Register result = ToRegister(instr->result());
2429 2428
2430 __ AssertString(input); 2429 __ AssertString(input);
2431 2430
2432 __ lw(result, FieldMemOperand(input, String::kHashFieldOffset)); 2431 __ lw(result, FieldMemOperand(input, String::kHashFieldOffset));
2433 __ IndexFromHash(result, result); 2432 __ IndexFromHash(result, result);
2434 } 2433 }
2435 2434
2436 2435
2437 void LCodeGen::DoHasCachedArrayIndexAndBranch( 2436 void LCodeGen::DoHasCachedArrayIndexAndBranch(
2438 LHasCachedArrayIndexAndBranch* instr) { 2437 LHasCachedArrayIndexAndBranch* instr) {
2439 Register input = ToRegister(instr->value()); 2438 Register input = ToRegister(instr->value());
2440 Register scratch = scratch0(); 2439 Register scratch = scratch0();
2441 2440
2442 int true_block = chunk_->LookupDestination(instr->true_block_id());
2443 int false_block = chunk_->LookupDestination(instr->false_block_id());
2444
2445 __ lw(scratch, 2441 __ lw(scratch,
2446 FieldMemOperand(input, String::kHashFieldOffset)); 2442 FieldMemOperand(input, String::kHashFieldOffset));
2447 __ And(at, scratch, Operand(String::kContainsCachedArrayIndexMask)); 2443 __ And(at, scratch, Operand(String::kContainsCachedArrayIndexMask));
2448 EmitBranch(true_block, false_block, eq, at, Operand(zero_reg)); 2444 EmitBranch(instr, eq, at, Operand(zero_reg));
2449 } 2445 }
2450 2446
2451 2447
2452 // Branches to a label or falls through with the answer in flags. Trashes 2448 // Branches to a label or falls through with the answer in flags. Trashes
2453 // the temp registers, but not the input. 2449 // the temp registers, but not the input.
2454 void LCodeGen::EmitClassOfTest(Label* is_true, 2450 void LCodeGen::EmitClassOfTest(Label* is_true,
2455 Label* is_false, 2451 Label* is_false,
2456 Handle<String>class_name, 2452 Handle<String>class_name,
2457 Register input, 2453 Register input,
2458 Register temp, 2454 Register temp,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2514 // On MIPS, the caller must do the comparison with Handle<String>class_name. 2510 // On MIPS, the caller must do the comparison with Handle<String>class_name.
2515 } 2511 }
2516 2512
2517 2513
2518 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 2514 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
2519 Register input = ToRegister(instr->value()); 2515 Register input = ToRegister(instr->value());
2520 Register temp = scratch0(); 2516 Register temp = scratch0();
2521 Register temp2 = ToRegister(instr->temp()); 2517 Register temp2 = ToRegister(instr->temp());
2522 Handle<String> class_name = instr->hydrogen()->class_name(); 2518 Handle<String> class_name = instr->hydrogen()->class_name();
2523 2519
2524 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2520 EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2525 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2521 class_name, input, temp, temp2);
2526 2522
2527 Label* true_label = chunk_->GetAssemblyLabel(true_block); 2523 EmitBranch(instr, eq, temp, Operand(class_name));
2528 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2529
2530 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2);
2531
2532 EmitBranch(true_block, false_block, eq, temp, Operand(class_name));
2533 } 2524 }
2534 2525
2535 2526
2536 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { 2527 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
2537 Register reg = ToRegister(instr->value()); 2528 Register reg = ToRegister(instr->value());
2538 Register temp = ToRegister(instr->temp()); 2529 Register temp = ToRegister(instr->temp());
2539 int true_block = instr->true_block_id();
2540 int false_block = instr->false_block_id();
2541 2530
2542 __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); 2531 __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
2543 EmitBranch(true_block, false_block, eq, temp, Operand(instr->map())); 2532 EmitBranch(instr, eq, temp, Operand(instr->map()));
2544 } 2533 }
2545 2534
2546 2535
2547 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { 2536 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
2548 Label true_label, done; 2537 Label true_label, done;
2549 ASSERT(ToRegister(instr->left()).is(a0)); // Object is in a0. 2538 ASSERT(ToRegister(instr->left()).is(a0)); // Object is in a0.
2550 ASSERT(ToRegister(instr->right()).is(a1)); // Function is in a1. 2539 ASSERT(ToRegister(instr->right()).is(a1)); // Function is in a1.
2551 Register result = ToRegister(instr->result()); 2540 Register result = ToRegister(instr->result());
2552 ASSERT(result.is(v0)); 2541 ASSERT(result.is(v0));
2553 2542
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
2853 2842
2854 if (instr->hydrogen()->DeoptimizesOnHole()) { 2843 if (instr->hydrogen()->DeoptimizesOnHole()) {
2855 DeoptimizeIf(eq, instr->environment(), scratch, Operand(at)); 2844 DeoptimizeIf(eq, instr->environment(), scratch, Operand(at));
2856 } else { 2845 } else {
2857 __ Branch(&skip_assignment, ne, scratch, Operand(at)); 2846 __ Branch(&skip_assignment, ne, scratch, Operand(at));
2858 } 2847 }
2859 } 2848 }
2860 2849
2861 __ sw(value, target); 2850 __ sw(value, target);
2862 if (instr->hydrogen()->NeedsWriteBarrier()) { 2851 if (instr->hydrogen()->NeedsWriteBarrier()) {
2863 HType type = instr->hydrogen()->value()->type();
2864 SmiCheck check_needed = 2852 SmiCheck check_needed =
2865 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 2853 instr->hydrogen()->value()->IsHeapObject()
2854 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2866 __ RecordWriteContextSlot(context, 2855 __ RecordWriteContextSlot(context,
2867 target.offset(), 2856 target.offset(),
2868 value, 2857 value,
2869 scratch0(), 2858 scratch0(),
2870 GetRAState(), 2859 GetRAState(),
2871 kSaveFPRegs, 2860 kSaveFPRegs,
2872 EMIT_REMEMBERED_SET, 2861 EMIT_REMEMBERED_SET,
2873 check_needed); 2862 check_needed);
2874 } 2863 }
2875 2864
(...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after
3618 } 3607 }
3619 3608
3620 3609
3621 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { 3610 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3622 Register input = ToRegister(instr->value()); 3611 Register input = ToRegister(instr->value());
3623 Register result = ToRegister(instr->result()); 3612 Register result = ToRegister(instr->result());
3624 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); 3613 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
3625 Label done; 3614 Label done;
3626 __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg)); 3615 __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg));
3627 __ mov(result, input); 3616 __ mov(result, input);
3617 __ subu(result, zero_reg, input);
3628 // Overflow if result is still negative, i.e. 0x80000000. 3618 // Overflow if result is still negative, i.e. 0x80000000.
3629 DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); 3619 DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg));
3630 __ bind(&done); 3620 __ bind(&done);
3631 } 3621 }
3632 3622
3633 3623
3634 void LCodeGen::DoMathAbs(LMathAbs* instr) { 3624 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3635 // Class for deferred case. 3625 // Class for deferred case.
3636 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { 3626 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
3637 public: 3627 public:
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
4037 CALL_AS_FUNCTION, 4027 CALL_AS_FUNCTION,
4038 A1_UNINITIALIZED); 4028 A1_UNINITIALIZED);
4039 } 4029 }
4040 4030
4041 4031
4042 void LCodeGen::DoCallNew(LCallNew* instr) { 4032 void LCodeGen::DoCallNew(LCallNew* instr) {
4043 ASSERT(ToRegister(instr->constructor()).is(a1)); 4033 ASSERT(ToRegister(instr->constructor()).is(a1));
4044 ASSERT(ToRegister(instr->result()).is(v0)); 4034 ASSERT(ToRegister(instr->result()).is(v0));
4045 4035
4046 __ li(a0, Operand(instr->arity())); 4036 __ li(a0, Operand(instr->arity()));
4047 if (FLAG_optimize_constructed_arrays) { 4037 // No cell in a2 for construct type feedback in optimized code
4048 // No cell in a2 for construct type feedback in optimized code 4038 Handle<Object> undefined_value(isolate()->factory()->undefined_value());
4049 Handle<Object> undefined_value(isolate()->heap()->undefined_value(), 4039 __ li(a2, Operand(undefined_value));
4050 isolate());
4051 __ li(a2, Operand(undefined_value));
4052 }
4053 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); 4040 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
4054 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4041 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4055 } 4042 }
4056 4043
4057 4044
4058 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { 4045 void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
4059 ASSERT(ToRegister(instr->constructor()).is(a1)); 4046 ASSERT(ToRegister(instr->constructor()).is(a1));
4060 ASSERT(ToRegister(instr->result()).is(v0)); 4047 ASSERT(ToRegister(instr->result()).is(v0));
4061 ASSERT(FLAG_optimize_constructed_arrays);
4062 4048
4063 __ li(a0, Operand(instr->arity())); 4049 __ li(a0, Operand(instr->arity()));
4064 __ li(a2, Operand(instr->hydrogen()->property_cell())); 4050 __ li(a2, Operand(instr->hydrogen()->property_cell()));
4065 ElementsKind kind = instr->hydrogen()->elements_kind(); 4051 ElementsKind kind = instr->hydrogen()->elements_kind();
4066 bool disable_allocation_sites = 4052 bool disable_allocation_sites =
4067 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE); 4053 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE);
4068 4054
4069 if (instr->arity() == 0) { 4055 if (instr->arity() == 0) {
4070 ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites); 4056 ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites);
4071 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4057 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
4146 GetRAState(), 4132 GetRAState(),
4147 kSaveFPRegs, 4133 kSaveFPRegs,
4148 OMIT_REMEMBERED_SET, 4134 OMIT_REMEMBERED_SET,
4149 OMIT_SMI_CHECK); 4135 OMIT_SMI_CHECK);
4150 } 4136 }
4151 } 4137 }
4152 4138
4153 // Do the store. 4139 // Do the store.
4154 Register value = ToRegister(instr->value()); 4140 Register value = ToRegister(instr->value());
4155 ASSERT(!object.is(value)); 4141 ASSERT(!object.is(value));
4156 HType type = instr->hydrogen()->value()->type();
4157 SmiCheck check_needed = 4142 SmiCheck check_needed =
4158 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 4143 instr->hydrogen()->value()->IsHeapObject()
4144 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4159 if (access.IsInobject()) { 4145 if (access.IsInobject()) {
4160 __ sw(value, FieldMemOperand(object, offset)); 4146 __ sw(value, FieldMemOperand(object, offset));
4161 if (instr->hydrogen()->NeedsWriteBarrier()) { 4147 if (instr->hydrogen()->NeedsWriteBarrier()) {
4162 // Update the write barrier for the object for in-object properties. 4148 // Update the write barrier for the object for in-object properties.
4163 __ RecordWriteField(object, 4149 __ RecordWriteField(object,
4164 offset, 4150 offset,
4165 value, 4151 value,
4166 scratch, 4152 scratch,
4167 GetRAState(), 4153 GetRAState(),
4168 kSaveFPRegs, 4154 kSaveFPRegs,
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
4373 __ addu(scratch, elements, scratch); 4359 __ addu(scratch, elements, scratch);
4374 } else { 4360 } else {
4375 __ sll(scratch, key, kPointerSizeLog2); 4361 __ sll(scratch, key, kPointerSizeLog2);
4376 __ addu(scratch, elements, scratch); 4362 __ addu(scratch, elements, scratch);
4377 } 4363 }
4378 offset = FixedArray::OffsetOfElementAt(instr->additional_index()); 4364 offset = FixedArray::OffsetOfElementAt(instr->additional_index());
4379 } 4365 }
4380 __ sw(value, FieldMemOperand(store_base, offset)); 4366 __ sw(value, FieldMemOperand(store_base, offset));
4381 4367
4382 if (instr->hydrogen()->NeedsWriteBarrier()) { 4368 if (instr->hydrogen()->NeedsWriteBarrier()) {
4383 HType type = instr->hydrogen()->value()->type();
4384 SmiCheck check_needed = 4369 SmiCheck check_needed =
4385 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 4370 instr->hydrogen()->value()->IsHeapObject()
4371 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4386 // Compute address of modified element and store it into key register. 4372 // Compute address of modified element and store it into key register.
4387 __ Addu(key, store_base, Operand(offset - kHeapObjectTag)); 4373 __ Addu(key, store_base, Operand(offset - kHeapObjectTag));
4388 __ RecordWrite(elements, 4374 __ RecordWrite(elements,
4389 key, 4375 key,
4390 value, 4376 value,
4391 GetRAState(), 4377 GetRAState(),
4392 kSaveFPRegs, 4378 kSaveFPRegs,
4393 EMIT_REMEMBERED_SET, 4379 EMIT_REMEMBERED_SET,
4394 check_needed); 4380 check_needed);
4395 } 4381 }
(...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after
5126 5112
5127 5113
5128 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 5114 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5129 LOperand* input = instr->value(); 5115 LOperand* input = instr->value();
5130 __ And(at, ToRegister(input), Operand(kSmiTagMask)); 5116 __ And(at, ToRegister(input), Operand(kSmiTagMask));
5131 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); 5117 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg));
5132 } 5118 }
5133 5119
5134 5120
5135 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 5121 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5136 LOperand* input = instr->value(); 5122 if (!instr->hydrogen()->value()->IsHeapObject()) {
5137 __ And(at, ToRegister(input), Operand(kSmiTagMask)); 5123 LOperand* input = instr->value();
5138 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); 5124 __ And(at, ToRegister(input), Operand(kSmiTagMask));
5125 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg));
5126 }
5139 } 5127 }
5140 5128
5141 5129
5142 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 5130 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5143 Register input = ToRegister(instr->value()); 5131 Register input = ToRegister(instr->value());
5144 Register scratch = scratch0(); 5132 Register scratch = scratch0();
5145 5133
5146 __ GetObjectType(input, scratch, scratch); 5134 __ GetObjectType(input, scratch, scratch);
5147 5135
5148 if (instr->hydrogen()->is_interval_check()) { 5136 if (instr->hydrogen()->is_interval_check()) {
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
5286 if (!instr->hydrogen()->CanOmitPrototypeChecks()) { 5274 if (!instr->hydrogen()->CanOmitPrototypeChecks()) {
5287 for (int i = 0; i < prototypes->length(); i++) { 5275 for (int i = 0; i < prototypes->length(); i++) {
5288 __ LoadHeapObject(prototype_reg, prototypes->at(i)); 5276 __ LoadHeapObject(prototype_reg, prototypes->at(i));
5289 __ lw(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset)); 5277 __ lw(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset));
5290 DoCheckMapCommon(map_reg, maps->at(i), instr->environment()); 5278 DoCheckMapCommon(map_reg, maps->at(i), instr->environment());
5291 } 5279 }
5292 } 5280 }
5293 } 5281 }
5294 5282
5295 5283
5284 void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
5285 class DeferredAllocateObject: public LDeferredCode {
5286 public:
5287 DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr)
5288 : LDeferredCode(codegen), instr_(instr) { }
5289 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); }
5290 virtual LInstruction* instr() { return instr_; }
5291 private:
5292 LAllocateObject* instr_;
5293 };
5294
5295 DeferredAllocateObject* deferred =
5296 new(zone()) DeferredAllocateObject(this, instr);
5297
5298 Register result = ToRegister(instr->result());
5299 Register scratch = ToRegister(instr->temp());
5300 Register scratch2 = ToRegister(instr->temp2());
5301 Handle<JSFunction> constructor = instr->hydrogen()->constructor();
5302 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
5303 int instance_size = initial_map->instance_size();
5304 ASSERT(initial_map->pre_allocated_property_fields() +
5305 initial_map->unused_property_fields() -
5306 initial_map->inobject_properties() == 0);
5307
5308 __ Allocate(instance_size, result, scratch, scratch2, deferred->entry(),
5309 TAG_OBJECT);
5310
5311 __ bind(deferred->exit());
5312 if (FLAG_debug_code) {
5313 Label is_in_new_space;
5314 __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
5315 __ Abort("Allocated object is not in new-space");
5316 __ bind(&is_in_new_space);
5317 }
5318
5319 // Load the initial map.
5320 Register map = scratch;
5321 __ LoadHeapObject(map, constructor);
5322 __ lw(map, FieldMemOperand(map, JSFunction::kPrototypeOrInitialMapOffset));
5323
5324 // Initialize map and fields of the newly allocated object.
5325 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
5326 __ sw(map, FieldMemOperand(result, JSObject::kMapOffset));
5327 __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
5328 __ sw(scratch, FieldMemOperand(result, JSObject::kElementsOffset));
5329 __ sw(scratch, FieldMemOperand(result, JSObject::kPropertiesOffset));
5330 if (initial_map->inobject_properties() != 0) {
5331 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
5332 for (int i = 0; i < initial_map->inobject_properties(); i++) {
5333 int property_offset = JSObject::kHeaderSize + i * kPointerSize;
5334 __ sw(scratch, FieldMemOperand(result, property_offset));
5335 }
5336 }
5337 }
5338
5339
5340 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
5341 Register result = ToRegister(instr->result());
5342 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
5343 int instance_size = initial_map->instance_size();
5344
5345 // TODO(3095996): Get rid of this. For now, we need to make the
5346 // result register contain a valid pointer because it is already
5347 // contained in the register pointer map.
5348 __ mov(result, zero_reg);
5349
5350 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
5351 __ li(a0, Operand(Smi::FromInt(instance_size)));
5352 __ push(a0);
5353 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
5354 __ StoreToSafepointRegisterSlot(v0, result);
5355 }
5356
5357
5296 void LCodeGen::DoAllocate(LAllocate* instr) { 5358 void LCodeGen::DoAllocate(LAllocate* instr) {
5297 class DeferredAllocate: public LDeferredCode { 5359 class DeferredAllocate: public LDeferredCode {
5298 public: 5360 public:
5299 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) 5361 DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
5300 : LDeferredCode(codegen), instr_(instr) { } 5362 : LDeferredCode(codegen), instr_(instr) { }
5301 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } 5363 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); }
5302 virtual LInstruction* instr() { return instr_; } 5364 virtual LInstruction* instr() { return instr_; }
5303 private: 5365 private:
5304 LAllocate* instr_; 5366 LAllocate* instr_;
5305 }; 5367 };
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
5453 void LCodeGen::DoTypeof(LTypeof* instr) { 5515 void LCodeGen::DoTypeof(LTypeof* instr) {
5454 ASSERT(ToRegister(instr->result()).is(v0)); 5516 ASSERT(ToRegister(instr->result()).is(v0));
5455 Register input = ToRegister(instr->value()); 5517 Register input = ToRegister(instr->value());
5456 __ push(input); 5518 __ push(input);
5457 CallRuntime(Runtime::kTypeof, 1, instr); 5519 CallRuntime(Runtime::kTypeof, 1, instr);
5458 } 5520 }
5459 5521
5460 5522
5461 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 5523 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
5462 Register input = ToRegister(instr->value()); 5524 Register input = ToRegister(instr->value());
5463 int true_block = chunk_->LookupDestination(instr->true_block_id());
5464 int false_block = chunk_->LookupDestination(instr->false_block_id());
5465 Label* true_label = chunk_->GetAssemblyLabel(true_block);
5466 Label* false_label = chunk_->GetAssemblyLabel(false_block);
5467 5525
5468 Register cmp1 = no_reg; 5526 Register cmp1 = no_reg;
5469 Operand cmp2 = Operand(no_reg); 5527 Operand cmp2 = Operand(no_reg);
5470 5528
5471 Condition final_branch_condition = EmitTypeofIs(true_label, 5529 Condition final_branch_condition = EmitTypeofIs(instr->TrueLabel(chunk_),
5472 false_label, 5530 instr->FalseLabel(chunk_),
5473 input, 5531 input,
5474 instr->type_literal(), 5532 instr->type_literal(),
5475 cmp1, 5533 cmp1,
5476 cmp2); 5534 cmp2);
5477 5535
5478 ASSERT(cmp1.is_valid()); 5536 ASSERT(cmp1.is_valid());
5479 ASSERT(!cmp2.is_reg() || cmp2.rm().is_valid()); 5537 ASSERT(!cmp2.is_reg() || cmp2.rm().is_valid());
5480 5538
5481 if (final_branch_condition != kNoCondition) { 5539 if (final_branch_condition != kNoCondition) {
5482 EmitBranch(true_block, false_block, final_branch_condition, cmp1, cmp2); 5540 EmitBranch(instr, final_branch_condition, cmp1, cmp2);
5483 } 5541 }
5484 } 5542 }
5485 5543
5486 5544
5487 Condition LCodeGen::EmitTypeofIs(Label* true_label, 5545 Condition LCodeGen::EmitTypeofIs(Label* true_label,
5488 Label* false_label, 5546 Label* false_label,
5489 Register input, 5547 Register input,
5490 Handle<String> type_name, 5548 Handle<String> type_name,
5491 Register& cmp1, 5549 Register& cmp1,
5492 Operand& cmp2) { 5550 Operand& cmp2) {
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
5585 cmp2 = Operand(zero_reg); // Set to valid regs, to avoid caller assertion. 5643 cmp2 = Operand(zero_reg); // Set to valid regs, to avoid caller assertion.
5586 __ Branch(false_label); 5644 __ Branch(false_label);
5587 } 5645 }
5588 5646
5589 return final_branch_condition; 5647 return final_branch_condition;
5590 } 5648 }
5591 5649
5592 5650
5593 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 5651 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
5594 Register temp1 = ToRegister(instr->temp()); 5652 Register temp1 = ToRegister(instr->temp());
5595 int true_block = chunk_->LookupDestination(instr->true_block_id());
5596 int false_block = chunk_->LookupDestination(instr->false_block_id());
5597 5653
5598 EmitIsConstructCall(temp1, scratch0()); 5654 EmitIsConstructCall(temp1, scratch0());
5599 5655
5600 EmitBranch(true_block, false_block, eq, temp1, 5656 EmitBranch(instr, eq, temp1,
5601 Operand(Smi::FromInt(StackFrame::CONSTRUCT))); 5657 Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
5602 } 5658 }
5603 5659
5604 5660
5605 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { 5661 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) {
5606 ASSERT(!temp1.is(temp2)); 5662 ASSERT(!temp1.is(temp2));
5607 // Get the frame pointer for the calling frame. 5663 // Get the frame pointer for the calling frame.
5608 __ lw(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 5664 __ lw(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
5609 5665
5610 // Skip the arguments adaptor frame if it exists. 5666 // Skip the arguments adaptor frame if it exists.
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
5741 // the deferred code. 5797 // the deferred code.
5742 } 5798 }
5743 } 5799 }
5744 5800
5745 5801
5746 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 5802 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
5747 // This is a pseudo-instruction that ensures that the environment here is 5803 // This is a pseudo-instruction that ensures that the environment here is
5748 // properly registered for deoptimization and records the assembler's PC 5804 // properly registered for deoptimization and records the assembler's PC
5749 // offset. 5805 // offset.
5750 LEnvironment* environment = instr->environment(); 5806 LEnvironment* environment = instr->environment();
5751 environment->SetSpilledRegisters(instr->SpilledRegisterArray(),
5752 instr->SpilledDoubleRegisterArray());
5753 5807
5754 // If the environment were already registered, we would have no way of 5808 // If the environment were already registered, we would have no way of
5755 // backpatching it with the spill slot operands. 5809 // backpatching it with the spill slot operands.
5756 ASSERT(!environment->HasBeenRegistered()); 5810 ASSERT(!environment->HasBeenRegistered());
5757 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 5811 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
5758 ASSERT(osr_pc_offset_ == -1); 5812
5759 osr_pc_offset_ = masm()->pc_offset(); 5813 // Normally we record the first unknown OSR value as the entrypoint to the OSR
5814 // code, but if there were none, record the entrypoint here.
5815 if (osr_pc_offset_ == -1) osr_pc_offset_ = masm()->pc_offset();
5760 } 5816 }
5761 5817
5762 5818
5763 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 5819 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
5764 Register result = ToRegister(instr->result()); 5820 Register result = ToRegister(instr->result());
5765 Register object = ToRegister(instr->object()); 5821 Register object = ToRegister(instr->object());
5766 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 5822 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
5767 DeoptimizeIf(eq, instr->environment(), object, Operand(at)); 5823 DeoptimizeIf(eq, instr->environment(), object, Operand(at));
5768 5824
5769 Register null_value = t1; 5825 Register null_value = t1;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
5848 __ Subu(scratch, result, scratch); 5904 __ Subu(scratch, result, scratch);
5849 __ lw(result, FieldMemOperand(scratch, 5905 __ lw(result, FieldMemOperand(scratch,
5850 FixedArray::kHeaderSize - kPointerSize)); 5906 FixedArray::kHeaderSize - kPointerSize));
5851 __ bind(&done); 5907 __ bind(&done);
5852 } 5908 }
5853 5909
5854 5910
5855 #undef __ 5911 #undef __
5856 5912
5857 } } // namespace v8::internal 5913 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/mips/lithium-codegen-mips.h ('k') | src/mips/lithium-mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698