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

Side by Side Diff: src/a64/lithium-codegen-a64.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/a64/lithium-codegen-a64.h ('k') | src/a64/macro-assembler-a64.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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 public: 70 public:
71 BranchOnCondition(LCodeGen* codegen, Condition cond) 71 BranchOnCondition(LCodeGen* codegen, Condition cond)
72 : BranchGenerator(codegen), 72 : BranchGenerator(codegen),
73 cond_(cond) { } 73 cond_(cond) { }
74 74
75 virtual void Emit(Label* label) const { 75 virtual void Emit(Label* label) const {
76 __ B(cond_, label); 76 __ B(cond_, label);
77 } 77 }
78 78
79 virtual void EmitInverted(Label* label) const { 79 virtual void EmitInverted(Label* label) const {
80 __ B(InvertCondition(cond_), label); 80 if (cond_ != al) {
81 __ B(InvertCondition(cond_), label);
82 }
81 } 83 }
82 84
83 private: 85 private:
84 Condition cond_; 86 Condition cond_;
85 }; 87 };
86 88
87 89
88 // Emit code to compare lhs and rhs and branch if the condition holds. 90 // Emit code to compare lhs and rhs and branch if the condition holds.
89 // This uses MacroAssembler's CompareAndBranch function so it will handle 91 // This uses MacroAssembler's CompareAndBranch function so it will handle
90 // converting the comparison to Cbz/Cbnz if the right-hand side is 0. 92 // converting the comparison to Cbz/Cbnz if the right-hand side is 0.
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 } 162 }
161 } 163 }
162 164
163 private: 165 private:
164 Condition cond_; 166 Condition cond_;
165 const Register& value_; 167 const Register& value_;
166 uint64_t mask_; 168 uint64_t mask_;
167 }; 169 };
168 170
169 171
172 // Test the input and branch if it is non-zero and not a NaN.
173 class BranchIfNonZeroNumber : public BranchGenerator {
174 public:
175 BranchIfNonZeroNumber(LCodeGen* codegen, const FPRegister& value,
176 const FPRegister& scratch)
177 : BranchGenerator(codegen), value_(value), scratch_(scratch) { }
178
179 virtual void Emit(Label* label) const {
180 __ Fabs(scratch_, value_);
181 // Compare with 0.0. Because scratch_ is positive, the result can be one of
182 // nZCv (equal), nzCv (greater) or nzCV (unordered).
183 __ Fcmp(scratch_, 0.0);
184 __ B(gt, label);
185 }
186
187 virtual void EmitInverted(Label* label) const {
188 __ Fabs(scratch_, value_);
189 __ Fcmp(scratch_, 0.0);
190 __ B(le, label);
191 }
192
193 private:
194 const FPRegister& value_;
195 const FPRegister& scratch_;
196 };
197
198
170 void LCodeGen::WriteTranslation(LEnvironment* environment, 199 void LCodeGen::WriteTranslation(LEnvironment* environment,
171 Translation* translation) { 200 Translation* translation) {
172 if (environment == NULL) return; 201 if (environment == NULL) return;
173 202
174 // The translation includes one command per value in the environment. 203 // The translation includes one command per value in the environment.
175 int translation_size = environment->translation_size(); 204 int translation_size = environment->translation_size();
176 // The output frame height does not include the parameters. 205 // The output frame height does not include the parameters.
177 int height = translation_size - environment->parameter_count(); 206 int height = translation_size - environment->parameter_count();
178 207
179 WriteTranslation(environment->outer(), translation); 208 WriteTranslation(environment->outer(), translation);
(...skipping 25 matching lines...) Expand all
205 break; 234 break;
206 case ARGUMENTS_ADAPTOR: 235 case ARGUMENTS_ADAPTOR:
207 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); 236 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
208 break; 237 break;
209 default: 238 default:
210 UNREACHABLE(); 239 UNREACHABLE();
211 } 240 }
212 241
213 for (int i = 0; i < translation_size; ++i) { 242 for (int i = 0; i < translation_size; ++i) {
214 LOperand* value = environment->values()->at(i); 243 LOperand* value = environment->values()->at(i);
215 // spilled_registers_ and spilled_double_registers_ are either
216 // both NULL or both set.
217 if ((environment->spilled_registers() != NULL) && (value != NULL)) {
218 if (value->IsRegister() &&
219 (environment->spilled_registers()[value->index()] != NULL)) {
220 translation->MarkDuplicate();
221 AddToTranslation(translation,
222 environment->spilled_registers()[value->index()],
223 environment->HasTaggedValueAt(i),
224 environment->HasUint32ValueAt(i));
225 } else if (
226 value->IsDoubleRegister() &&
227 (environment->spilled_double_registers()[value->index()] != NULL)) {
228 translation->MarkDuplicate();
229 AddToTranslation(
230 translation,
231 environment->spilled_double_registers()[value->index()],
232 false,
233 false);
234 }
235 }
236 244
237 // TODO(mstarzinger): Introduce marker operands to indicate that this value 245 // TODO(mstarzinger): Introduce marker operands to indicate that this value
238 // is not present and must be reconstructed from the deoptimizer. Currently 246 // is not present and must be reconstructed from the deoptimizer. Currently
239 // this is only used for the arguments object. 247 // this is only used for the arguments object.
240 if (value == NULL) { 248 if (value == NULL) {
241 int arguments_count = environment->values()->length() - translation_size; 249 int arguments_count = environment->values()->length() - translation_size;
242 translation->BeginArgumentsObject(arguments_count); 250 translation->BeginArgumentsObject(arguments_count);
243 for (int i = 0; i < arguments_count; ++i) { 251 for (int i = 0; i < arguments_count; ++i) {
244 LOperand* value = environment->values()->at(translation_size + i); 252 LOperand* value = environment->values()->at(translation_size + i);
245 ASSERT(environment->spilled_registers() == NULL ||
246 !value->IsRegister() ||
247 environment->spilled_registers()[value->index()] == NULL);
248 ASSERT(environment->spilled_registers() == NULL ||
249 !value->IsDoubleRegister() ||
250 environment->spilled_double_registers()[value->index()] == NULL);
251 AddToTranslation(translation, 253 AddToTranslation(translation,
252 value, 254 value,
253 environment->HasTaggedValueAt(translation_size + i), 255 environment->HasTaggedValueAt(translation_size + i),
254 environment->HasUint32ValueAt(translation_size + i)); 256 environment->HasUint32ValueAt(translation_size + i));
255 } 257 }
256 continue; 258 continue;
257 } 259 }
258 260
259 AddToTranslation(translation, 261 AddToTranslation(translation,
260 value, 262 value,
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 376 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
375 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 377 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
376 } 378 }
377 379
378 380
379 void LCodeGen::DoCallNew(LCallNew* instr) { 381 void LCodeGen::DoCallNew(LCallNew* instr) {
380 ASSERT(instr->IsMarkedAsCall()); 382 ASSERT(instr->IsMarkedAsCall());
381 ASSERT(ToRegister(instr->constructor()).is(x1)); 383 ASSERT(ToRegister(instr->constructor()).is(x1));
382 384
383 __ Mov(x0, instr->arity()); 385 __ Mov(x0, instr->arity());
384 if (FLAG_optimize_constructed_arrays) { 386 // No cell in x2 for construct type feedback in optimized code.
385 // No cell in x2 for construct type feedback in optimized code. 387 Handle<Object> undefined_value(isolate()->factory()->undefined_value());
386 Handle<Object> undefined_value(isolate()->heap()->undefined_value(), 388 __ Mov(x2, Operand(undefined_value));
387 isolate());
388 __ Mov(x2, Operand(undefined_value));
389 }
390 389
391 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); 390 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
392 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 391 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
393 392
394 ASSERT(ToRegister(instr->result()).is(x0)); 393 ASSERT(ToRegister(instr->result()).is(x0));
395 } 394 }
396 395
397 396
398 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { 397 void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
399 ASSERT(instr->IsMarkedAsCall()); 398 ASSERT(instr->IsMarkedAsCall());
400 ASSERT(ToRegister(instr->constructor()).is(x1)); 399 ASSERT(ToRegister(instr->constructor()).is(x1));
401 ASSERT(FLAG_optimize_constructed_arrays);
402 400
403 __ Mov(x0, Operand(instr->arity())); 401 __ Mov(x0, Operand(instr->arity()));
404 __ Mov(x2, Operand(instr->hydrogen()->property_cell())); 402 __ Mov(x2, Operand(instr->hydrogen()->property_cell()));
405 403
406 ElementsKind kind = instr->hydrogen()->elements_kind(); 404 ElementsKind kind = instr->hydrogen()->elements_kind();
407 bool disable_allocation_sites = 405 bool disable_allocation_sites =
408 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE); 406 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE);
409 407
410 if (instr->arity() == 0) { 408 if (instr->arity() == 0) {
411 ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites); 409 ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites);
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 516
519 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 517 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
520 int arguments, 518 int arguments,
521 Safepoint::DeoptMode deopt_mode) { 519 Safepoint::DeoptMode deopt_mode) {
522 RecordSafepoint( 520 RecordSafepoint(
523 pointers, Safepoint::kWithRegisters, arguments, deopt_mode); 521 pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
524 } 522 }
525 523
526 524
527 bool LCodeGen::GenerateCode() { 525 bool LCodeGen::GenerateCode() {
528 HPhase phase("Z_Code generation", chunk()); 526 LPhase phase("Z_Code generation", chunk());
529 ASSERT(is_unused()); 527 ASSERT(is_unused());
530 status_ = GENERATING; 528 status_ = GENERATING;
531 529
532 // Open a frame scope to indicate that there is a frame on the stack. The 530 // Open a frame scope to indicate that there is a frame on the stack. The
533 // NONE indicates that the scope shouldn't actually generate code to set up 531 // NONE indicates that the scope shouldn't actually generate code to set up
534 // the frame (that is done in GeneratePrologue). 532 // the frame (that is done in GeneratePrologue).
535 FrameScope frame_scope(masm_, StackFrame::NONE); 533 FrameScope frame_scope(masm_, StackFrame::NONE);
536 534
537 return GeneratePrologue() && 535 return GeneratePrologue() &&
538 GenerateBody() && 536 GenerateBody() &&
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 755
758 756
759 void LCodeGen::FinishCode(Handle<Code> code) { 757 void LCodeGen::FinishCode(Handle<Code> code) {
760 ASSERT(is_done()); 758 ASSERT(is_done());
761 code->set_stack_slots(GetStackSlotCount()); 759 code->set_stack_slots(GetStackSlotCount());
762 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); 760 code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
763 if (FLAG_weak_embedded_maps_in_optimized_code) { 761 if (FLAG_weak_embedded_maps_in_optimized_code) {
764 RegisterDependentCodeForEmbeddedMaps(code); 762 RegisterDependentCodeForEmbeddedMaps(code);
765 } 763 }
766 PopulateDeoptimizationData(code); 764 PopulateDeoptimizationData(code);
767 info()->CommitDependentMaps(code); 765 info()->CommitDependencies(code);
768 } 766 }
769 767
770 768
771 void LCodeGen::Abort(const char* reason) { 769 void LCodeGen::Abort(const char* reason) {
772 info()->set_bailout_reason(reason); 770 info()->set_bailout_reason(reason);
773 status_ = ABORTED; 771 status_ = ABORTED;
774 } 772 }
775 773
776 774
777 void LCodeGen::Comment(const char* format, ...) { 775 void LCodeGen::Comment(const char* format, ...) {
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
1195 template<class InstrType> 1193 template<class InstrType>
1196 void LCodeGen::EmitTestAndBranch(InstrType instr, 1194 void LCodeGen::EmitTestAndBranch(InstrType instr,
1197 Condition condition, 1195 Condition condition,
1198 const Register& value, 1196 const Register& value,
1199 uint64_t mask) { 1197 uint64_t mask) {
1200 TestAndBranch branch(this, condition, value, mask); 1198 TestAndBranch branch(this, condition, value, mask);
1201 EmitBranchGeneric(instr, branch); 1199 EmitBranchGeneric(instr, branch);
1202 } 1200 }
1203 1201
1204 1202
1203 template<class InstrType>
1204 void LCodeGen::EmitBranchIfNonZeroNumber(InstrType instr,
1205 const FPRegister& value,
1206 const FPRegister& scratch) {
1207 BranchIfNonZeroNumber branch(this, value, scratch);
1208 EmitBranchGeneric(instr, branch);
1209 }
1210
1211
1205 void LCodeGen::DoGap(LGap* gap) { 1212 void LCodeGen::DoGap(LGap* gap) {
1206 for (int i = LGap::FIRST_INNER_POSITION; 1213 for (int i = LGap::FIRST_INNER_POSITION;
1207 i <= LGap::LAST_INNER_POSITION; 1214 i <= LGap::LAST_INNER_POSITION;
1208 i++) { 1215 i++) {
1209 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); 1216 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
1210 LParallelMove* move = gap->GetParallelMove(inner_pos); 1217 LParallelMove* move = gap->GetParallelMove(inner_pos);
1211 if (move != NULL) { 1218 if (move != NULL) {
1212 resolver_.Resolve(move); 1219 resolver_.Resolve(move);
1213 } 1220 }
1214 } 1221 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1322 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr); 1329 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr);
1323 } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) { 1330 } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) {
1324 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr); 1331 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr);
1325 } else { 1332 } else {
1326 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); 1333 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
1327 } 1334 }
1328 __ StoreToSafepointRegisterSlot(x0, result); 1335 __ StoreToSafepointRegisterSlot(x0, result);
1329 } 1336 }
1330 1337
1331 1338
1339 void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
1340 class DeferredAllocateObject: public LDeferredCode {
1341 public:
1342 DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr)
1343 : LDeferredCode(codegen), instr_(instr) { }
1344 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); }
1345 virtual LInstruction* instr() { return instr_; }
1346 private:
1347 LAllocateObject* instr_;
1348 };
1349
1350 DeferredAllocateObject* deferred =
1351 new(zone()) DeferredAllocateObject(this, instr);
1352
1353 Register result = ToRegister(instr->result());
1354 Register scratch1 = ToRegister(instr->temp1());
1355 Register scratch2 = ToRegister(instr->temp2());
1356 Handle<JSFunction> constructor = instr->hydrogen()->constructor();
1357 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
1358 int instance_size = initial_map->instance_size();
1359
1360 ASSERT(initial_map->pre_allocated_property_fields() +
1361 initial_map->unused_property_fields() -
1362 initial_map->inobject_properties() == 0);
1363
1364 __ Allocate(instance_size, result, scratch1, scratch2, deferred->entry(),
1365 TAG_OBJECT);
1366
1367 __ Bind(deferred->exit());
1368 if (FLAG_debug_code) {
1369 Label is_in_new_space;
1370 __ JumpIfInNewSpace(result, &is_in_new_space);
1371 __ Abort("Allocated object is not in new-space");
1372 __ Bind(&is_in_new_space);
1373 }
1374
1375 // Load the initial map.
1376 Register map = scratch1;
1377 __ LoadHeapObject(map, constructor);
1378 __ Ldr(map, FieldMemOperand(map, JSFunction::kPrototypeOrInitialMapOffset));
1379
1380 // Initialize map and field of the newly allocated object.
1381 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
1382 __ Str(map, FieldMemOperand(result, JSObject::kMapOffset));
1383
1384 Register empty_array = scratch1;
1385 __ LoadRoot(empty_array, Heap::kEmptyFixedArrayRootIndex);
1386 __ Str(empty_array, FieldMemOperand(result, JSObject::kElementsOffset));
1387 __ Str(empty_array, FieldMemOperand(result, JSObject::kPropertiesOffset));
1388
1389 if (initial_map->inobject_properties() != 0) {
1390 Register undef = scratch1;
1391 __ LoadRoot(undef, Heap::kUndefinedValueRootIndex);
1392 for (int i = 0; i < initial_map->inobject_properties(); i++) {
1393 int property_offset = JSObject::kHeaderSize + i * kPointerSize;
1394 __ Str(undef, FieldMemOperand(result, property_offset));
1395 }
1396 }
1397 }
1398
1399
1400 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
1401 Register result = ToRegister(instr->result());
1402 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
1403 int instance_size = initial_map->instance_size();
1404
1405
1406 // TODO(3095996): Get rid of this. For now, we need to make the
1407 // result register contain a valid pointer because it is already
1408 // contained in the register pointer map.
1409 __ Mov(result, 0);
1410
1411 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
1412 __ Mov(x0, Operand(Smi::FromInt(instance_size)));
1413 __ Push(x0);
1414 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
1415 __ StoreToSafepointRegisterSlot(x0, result);
1416 }
1417
1418
1332 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 1419 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
1333 Register receiver = ToRegister(instr->receiver()); 1420 Register receiver = ToRegister(instr->receiver());
1334 Register function = ToRegister(instr->function()); 1421 Register function = ToRegister(instr->function());
1335 Register length = ToRegister(instr->length()); 1422 Register length = ToRegister(instr->length());
1336 Register elements = ToRegister(instr->elements()); 1423 Register elements = ToRegister(instr->elements());
1337 Register scratch = x5; 1424 Register scratch = x5;
1338 ASSERT(receiver.Is(x0)); // Used for parameter count. 1425 ASSERT(receiver.Is(x0)); // Used for parameter count.
1339 ASSERT(function.Is(x1)); // Required by InvokeFunction. 1426 ASSERT(function.Is(x1)); // Required by InvokeFunction.
1340 ASSERT(ToRegister(instr->result()).Is(x0)); 1427 ASSERT(ToRegister(instr->result()).Is(x0));
1341 ASSERT(instr->IsMarkedAsCall()); 1428 ASSERT(instr->IsMarkedAsCall());
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1529 1616
1530 if (r.IsInteger32()) { 1617 if (r.IsInteger32()) {
1531 ASSERT(!info()->IsStub()); 1618 ASSERT(!info()->IsStub());
1532 EmitCompareAndBranch(instr, ne, ToRegister32(instr->value()), 0); 1619 EmitCompareAndBranch(instr, ne, ToRegister32(instr->value()), 0);
1533 } else if (r.IsSmi()) { 1620 } else if (r.IsSmi()) {
1534 ASSERT(!info()->IsStub()); 1621 ASSERT(!info()->IsStub());
1535 STATIC_ASSERT(kSmiTag == 0); 1622 STATIC_ASSERT(kSmiTag == 0);
1536 EmitCompareAndBranch(instr, ne, ToRegister(instr->value()), 0); 1623 EmitCompareAndBranch(instr, ne, ToRegister(instr->value()), 0);
1537 } else if (r.IsDouble()) { 1624 } else if (r.IsDouble()) {
1538 DoubleRegister value = ToDoubleRegister(instr->value()); 1625 DoubleRegister value = ToDoubleRegister(instr->value());
1539 __ Fcmp(value, 0.0); 1626 // Test the double value. Zero and NaN are false.
1540 // If we got a NaN jump to the false branch. 1627 EmitBranchIfNonZeroNumber(instr, value, double_scratch());
1541 __ B(vs, false_label);
1542 EmitBranch(instr, ne);
1543 } else { 1628 } else {
1544 ASSERT(r.IsTagged()); 1629 ASSERT(r.IsTagged());
1545 Register value = ToRegister(instr->value()); 1630 Register value = ToRegister(instr->value());
1546 HType type = instr->hydrogen()->value()->type(); 1631 HType type = instr->hydrogen()->value()->type();
1547 1632
1548 if (type.IsBoolean()) { 1633 if (type.IsBoolean()) {
1549 ASSERT(!info()->IsStub()); 1634 ASSERT(!info()->IsStub());
1550 __ CompareRoot(value, Heap::kTrueValueRootIndex); 1635 __ CompareRoot(value, Heap::kTrueValueRootIndex);
1551 EmitBranch(instr, eq); 1636 EmitBranch(instr, eq);
1552 } else if (type.IsSmi()) { 1637 } else if (type.IsSmi()) {
1553 ASSERT(!info()->IsStub()); 1638 ASSERT(!info()->IsStub());
1554 EmitCompareAndBranch(instr, ne, value, Operand(Smi::FromInt(0))); 1639 EmitCompareAndBranch(instr, ne, value, Operand(Smi::FromInt(0)));
1640 } else if (type.IsJSArray()) {
1641 ASSERT(!info()->IsStub());
1642 EmitBranch(instr, al);
1643 } else if (type.IsHeapNumber()) {
1644 ASSERT(!info()->IsStub());
1645 __ Ldr(double_scratch(), FieldMemOperand(value,
1646 HeapNumber::kValueOffset));
1647 // Test the double value. Zero and NaN are false.
1648 EmitBranchIfNonZeroNumber(instr, double_scratch(), double_scratch());
1649 } else if (type.IsString()) {
1650 ASSERT(!info()->IsStub());
1651 Register temp = ToRegister(instr->temp1());
1652 __ Ldr(temp, FieldMemOperand(value, String::kLengthOffset));
1653 EmitCompareAndBranch(instr, ne, temp, 0);
1555 } else { 1654 } else {
1556 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); 1655 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
1557 // Avoid deopts in the case where we've never executed this path before. 1656 // Avoid deopts in the case where we've never executed this path before.
1558 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); 1657 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
1559 1658
1560 if (expected.Contains(ToBooleanStub::UNDEFINED)) { 1659 if (expected.Contains(ToBooleanStub::UNDEFINED)) {
1561 // undefined -> false. 1660 // undefined -> false.
1562 __ JumpIfRoot( 1661 __ JumpIfRoot(
1563 value, Heap::kUndefinedValueRootIndex, false_label); 1662 value, Heap::kUndefinedValueRootIndex, false_label);
1564 } 1663 }
1565 1664
1566 if (expected.Contains(ToBooleanStub::BOOLEAN)) { 1665 if (expected.Contains(ToBooleanStub::BOOLEAN)) {
1567 // Boolean -> its value. 1666 // Boolean -> its value.
1568 __ JumpIfRoot( 1667 __ JumpIfRoot(
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1635 __ Ldr(double_scratch(), 1734 __ Ldr(double_scratch(),
1636 FieldMemOperand(value, HeapNumber::kValueOffset)); 1735 FieldMemOperand(value, HeapNumber::kValueOffset));
1637 __ Fcmp(double_scratch(), 0.0); 1736 __ Fcmp(double_scratch(), 0.0);
1638 // If we got a NaN (overflow bit is set), jump to the false branch. 1737 // If we got a NaN (overflow bit is set), jump to the false branch.
1639 __ B(vs, false_label); 1738 __ B(vs, false_label);
1640 __ B(eq, false_label); 1739 __ B(eq, false_label);
1641 __ B(true_label); 1740 __ B(true_label);
1642 __ Bind(&not_heap_number); 1741 __ Bind(&not_heap_number);
1643 } 1742 }
1644 1743
1645 // We've seen something for the first time -> deopt. 1744 if (!expected.IsGeneric()) {
1646 Deoptimize(instr->environment()); 1745 // We've seen something for the first time -> deopt.
1746 // This can only happen if we are not generic already.
1747 Deoptimize(instr->environment());
1748 }
1647 } 1749 }
1648 } 1750 }
1649 } 1751 }
1650 1752
1651 1753
1652 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, 1754 void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
1653 int formal_parameter_count, 1755 int formal_parameter_count,
1654 int arity, 1756 int arity,
1655 LInstruction* instr, 1757 LInstruction* instr,
1656 CallKind call_kind, 1758 CallKind call_kind,
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1835 } 1937 }
1836 1938
1837 // If we didn't match a map, deoptimize. 1939 // If we didn't match a map, deoptimize.
1838 Deoptimize(instr->environment()); 1940 Deoptimize(instr->environment());
1839 1941
1840 __ Bind(&success); 1942 __ Bind(&success);
1841 } 1943 }
1842 1944
1843 1945
1844 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 1946 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
1845 // TODO(all): Depending of how we chose to implement the deopt, if we could 1947 if (!instr->hydrogen()->value()->IsHeapObject()) {
1846 // guarantee that we have a deopt handler reachable by a tbz instruction, 1948 // TODO(all): Depending of how we chose to implement the deopt, if we could
1847 // we could use tbz here and produce less code to support this instruction. 1949 // guarantee that we have a deopt handler reachable by a tbz instruction,
1848 DeoptimizeIfSmi(ToRegister(instr->value()), instr->environment()); 1950 // we could use tbz here and produce less code to support this instruction.
1951 DeoptimizeIfSmi(ToRegister(instr->value()), instr->environment());
1952 }
1849 } 1953 }
1850 1954
1851 1955
1852 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { 1956 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
1853 ZoneList<Handle<JSObject> >* prototypes = instr->prototypes(); 1957 ZoneList<Handle<JSObject> >* prototypes = instr->prototypes();
1854 ZoneList<Handle<Map> >* maps = instr->maps(); 1958 ZoneList<Handle<Map> >* maps = instr->maps();
1855 ASSERT(prototypes->length() == maps->length()); 1959 ASSERT(prototypes->length() == maps->length());
1856 1960
1857 if (!instr->hydrogen()->CanOmitPrototypeChecks()) { 1961 if (!instr->hydrogen()->CanOmitPrototypeChecks()) {
1858 // TODO(jbramley): The temp registers are only needed in this case. 1962 // TODO(jbramley): The temp registers are only needed in this case.
(...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after
2593 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { 2697 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) {
2594 if (!chunk_->GetLabel(i)->HasReplacement()) return i; 2698 if (!chunk_->GetLabel(i)->HasReplacement()) return i;
2595 } 2699 }
2596 return -1; 2700 return -1;
2597 } 2701 }
2598 2702
2599 2703
2600 void LCodeGen::EmitGoto(int block) { 2704 void LCodeGen::EmitGoto(int block) {
2601 // Do not emit jump if we are emitting a goto to the next block. 2705 // Do not emit jump if we are emitting a goto to the next block.
2602 if (!IsNextEmittedBlock(block)) { 2706 if (!IsNextEmittedBlock(block)) {
2603 __ B(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); 2707 __ B(chunk_->GetAssemblyLabel(LookupDestination(block)));
2604 } 2708 }
2605 } 2709 }
2606 2710
2607 2711
2608 void LCodeGen::DoGoto(LGoto* instr) { 2712 void LCodeGen::DoGoto(LGoto* instr) {
2609 EmitGoto(instr->block_id()); 2713 EmitGoto(instr->block_id());
2610 } 2714 }
2611 2715
2612 2716
2613 // HHasInstanceTypeAndBranch instruction is built with an interval of type 2717 // HHasInstanceTypeAndBranch instruction is built with an interval of type
(...skipping 27 matching lines...) Expand all
2641 if (from == FIRST_TYPE) return ls; 2745 if (from == FIRST_TYPE) return ls;
2642 UNREACHABLE(); 2746 UNREACHABLE();
2643 return eq; 2747 return eq;
2644 } 2748 }
2645 2749
2646 2750
2647 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 2751 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
2648 Register input = ToRegister(instr->value()); 2752 Register input = ToRegister(instr->value());
2649 Register scratch = ToRegister(instr->temp()); 2753 Register scratch = ToRegister(instr->temp());
2650 2754
2651 // TODO(all): When we'll have rebased, we can avoid the smi check if the 2755 if (!instr->hydrogen()->value()->IsHeapObject()) {
2652 // input is known to be a HeapObject. 2756 __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2653 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); 2757 }
2654 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); 2758 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen()));
2655 EmitBranch(instr, BranchCondition(instr->hydrogen())); 2759 EmitBranch(instr, BranchCondition(instr->hydrogen()));
2656 } 2760 }
2657 2761
2658 2762
2659 void LCodeGen::DoIn(LIn* instr) { 2763 void LCodeGen::DoIn(LIn* instr) {
2660 Register obj = ToRegister(instr->object()); 2764 Register obj = ToRegister(instr->object());
2661 Register key = ToRegister(instr->key()); 2765 Register key = ToRegister(instr->key());
2662 __ Push(key, obj); 2766 __ Push(key, obj);
2663 ASSERT(instr->HasPointerMap()); 2767 ASSERT(instr->HasPointerMap());
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
2879 __ IsInstanceJSObjectType(map, scratch, NULL); 2983 __ IsInstanceJSObjectType(map, scratch, NULL);
2880 // Flags have been updated by IsInstanceJSObjectType. We can now test the 2984 // Flags have been updated by IsInstanceJSObjectType. We can now test the
2881 // flags for "le" condition to check if the object's type is a valid 2985 // flags for "le" condition to check if the object's type is a valid
2882 // JS object type. 2986 // JS object type.
2883 EmitBranch(instr, le); 2987 EmitBranch(instr, le);
2884 } 2988 }
2885 2989
2886 2990
2887 Condition LCodeGen::EmitIsString(Register input, 2991 Condition LCodeGen::EmitIsString(Register input,
2888 Register temp1, 2992 Register temp1,
2889 Label* is_not_string) { 2993 Label* is_not_string,
2890 __ JumpIfSmi(input, is_not_string); 2994 SmiCheck check_needed = INLINE_SMI_CHECK) {
2995 if (check_needed == INLINE_SMI_CHECK) {
2996 __ JumpIfSmi(input, is_not_string);
2997 }
2891 __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE); 2998 __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE);
2892 2999
2893 return lt; 3000 return lt;
2894 } 3001 }
2895 3002
2896 3003
2897 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { 3004 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
2898 Register val = ToRegister(instr->value()); 3005 Register val = ToRegister(instr->value());
2899 Register scratch = ToRegister(instr->temp()); 3006 Register scratch = ToRegister(instr->temp());
2900 3007
2901 Condition true_cond = EmitIsString(val, scratch, instr->FalseLabel(chunk_)); 3008 SmiCheck check_needed =
3009 instr->hydrogen()->value()->IsHeapObject()
3010 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3011 Condition true_cond =
3012 EmitIsString(val, scratch, instr->FalseLabel(chunk_), check_needed);
2902 3013
2903 EmitBranch(instr, true_cond); 3014 EmitBranch(instr, true_cond);
2904 } 3015 }
2905 3016
2906 3017
2907 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 3018 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
2908 Register value = ToRegister(instr->value()); 3019 Register value = ToRegister(instr->value());
2909 STATIC_ASSERT(kSmiTag == 0); 3020 STATIC_ASSERT(kSmiTag == 0);
2910 EmitTestAndBranch(instr, eq, value, kSmiTagMask); 3021 EmitTestAndBranch(instr, eq, value, kSmiTagMask);
2911 } 3022 }
2912 3023
2913 3024
2914 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { 3025 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
2915 Register input = ToRegister(instr->value()); 3026 Register input = ToRegister(instr->value());
2916 Register temp = ToRegister(instr->temp()); 3027 Register temp = ToRegister(instr->temp());
2917 3028
2918 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); 3029 if (!instr->hydrogen()->value()->IsHeapObject()) {
3030 __ JumpIfSmi(input, instr->FalseLabel(chunk_));
3031 }
2919 __ Ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); 3032 __ Ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset));
2920 __ Ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); 3033 __ Ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
2921 3034
2922 // TODO(jbramley): Find a way to use Tbz here. 3035 EmitTestAndBranch(instr, ne, temp, 1 << Map::kIsUndetectable);
2923 __ Tst(temp, 1 << Map::kIsUndetectable);
2924 EmitBranch(instr, ne);
2925 } 3036 }
2926 3037
2927 3038
2928 static const char* LabelType(LLabel* label) { 3039 static const char* LabelType(LLabel* label) {
2929 if (label->is_loop_header()) return " (loop header)"; 3040 if (label->is_loop_header()) return " (loop header)";
2930 if (label->is_osr_entry()) return " (OSR entry)"; 3041 if (label->is_osr_entry()) return " (OSR entry)";
2931 return ""; 3042 return "";
2932 } 3043 }
2933 3044
2934 3045
(...skipping 1535 matching lines...) Expand 10 before | Expand all | Expand 10 after
4470 if (instr->hydrogen()->DeoptimizesOnHole()) { 4581 if (instr->hydrogen()->DeoptimizesOnHole()) {
4471 DeoptimizeIfRoot(scratch, Heap::kTheHoleValueRootIndex, 4582 DeoptimizeIfRoot(scratch, Heap::kTheHoleValueRootIndex,
4472 instr->environment()); 4583 instr->environment());
4473 } else { 4584 } else {
4474 __ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, &skip_assignment); 4585 __ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, &skip_assignment);
4475 } 4586 }
4476 } 4587 }
4477 4588
4478 __ Str(value, target); 4589 __ Str(value, target);
4479 if (instr->hydrogen()->NeedsWriteBarrier()) { 4590 if (instr->hydrogen()->NeedsWriteBarrier()) {
4480 HType type = instr->hydrogen()->value()->type();
4481 SmiCheck check_needed = 4591 SmiCheck check_needed =
4482 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 4592 instr->hydrogen()->value()->IsHeapObject()
4593 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4483 __ RecordWriteContextSlot(context, 4594 __ RecordWriteContextSlot(context,
4484 target.offset(), 4595 target.offset(),
4485 value, 4596 value,
4486 scratch, 4597 scratch,
4487 GetLinkRegisterState(), 4598 GetLinkRegisterState(),
4488 kSaveFPRegs, 4599 kSaveFPRegs,
4489 EMIT_REMEMBERED_SET, 4600 EMIT_REMEMBERED_SET,
4490 check_needed); 4601 check_needed);
4491 } 4602 }
4492 __ Bind(&skip_assignment); 4603 __ Bind(&skip_assignment);
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
4642 } else { 4753 } else {
4643 key = ToRegister(instr->key()); 4754 key = ToRegister(instr->key());
4644 bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi(); 4755 bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi();
4645 CalcKeyedArrayBaseRegister(store_base, elements, key, key_is_tagged, 4756 CalcKeyedArrayBaseRegister(store_base, elements, key, key_is_tagged,
4646 instr->hydrogen()->elements_kind()); 4757 instr->hydrogen()->elements_kind());
4647 offset = FixedArray::OffsetOfElementAt(instr->additional_index()); 4758 offset = FixedArray::OffsetOfElementAt(instr->additional_index());
4648 } 4759 }
4649 __ Str(value, FieldMemOperand(store_base, offset)); 4760 __ Str(value, FieldMemOperand(store_base, offset));
4650 4761
4651 if (instr->hydrogen()->NeedsWriteBarrier()) { 4762 if (instr->hydrogen()->NeedsWriteBarrier()) {
4652 HType type = instr->hydrogen()->value()->type(); 4763 SmiCheck check_needed =
4653 SmiCheck check_needed = type.IsHeapObject() 4764 instr->hydrogen()->value()->IsHeapObject()
4654 ? OMIT_SMI_CHECK 4765 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4655 : INLINE_SMI_CHECK;
4656 // Compute address of modified element and store it into key register. 4766 // Compute address of modified element and store it into key register.
4657 __ Add(key, store_base, offset - kHeapObjectTag); 4767 __ Add(key, store_base, offset - kHeapObjectTag);
4658 __ RecordWrite(elements, key, value, GetLinkRegisterState(), kSaveFPRegs, 4768 __ RecordWrite(elements, key, value, GetLinkRegisterState(), kSaveFPRegs,
4659 EMIT_REMEMBERED_SET, check_needed); 4769 EMIT_REMEMBERED_SET, check_needed);
4660 } 4770 }
4661 } 4771 }
4662 4772
4663 4773
4664 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 4774 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
4665 ASSERT(ToRegister(instr->object()).Is(x2)); 4775 ASSERT(ToRegister(instr->object()).Is(x2));
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
4713 temp1, 4823 temp1,
4714 GetLinkRegisterState(), 4824 GetLinkRegisterState(),
4715 kSaveFPRegs, 4825 kSaveFPRegs,
4716 OMIT_REMEMBERED_SET, 4826 OMIT_REMEMBERED_SET,
4717 OMIT_SMI_CHECK); 4827 OMIT_SMI_CHECK);
4718 } 4828 }
4719 } 4829 }
4720 4830
4721 // Do the store. 4831 // Do the store.
4722 Register value = ToRegister(instr->value()); 4832 Register value = ToRegister(instr->value());
4723 HType type = instr->hydrogen()->value()->type();
4724 SmiCheck check_needed = 4833 SmiCheck check_needed =
4725 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 4834 instr->hydrogen()->value()->IsHeapObject()
4835 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4726 if (access.IsInobject()) { 4836 if (access.IsInobject()) {
4727 __ Str(value, FieldMemOperand(object, offset)); 4837 __ Str(value, FieldMemOperand(object, offset));
4728 if (instr->hydrogen()->NeedsWriteBarrier()) { 4838 if (instr->hydrogen()->NeedsWriteBarrier()) {
4729 // Update the write barrier for the object for in-object properties. 4839 // Update the write barrier for the object for in-object properties.
4730 __ RecordWriteField(object, 4840 __ RecordWriteField(object,
4731 offset, 4841 offset,
4732 value, // Clobbered. 4842 value, // Clobbered.
4733 temp0, // Clobbered. 4843 temp0, // Clobbered.
4734 GetLinkRegisterState(), 4844 GetLinkRegisterState(),
4735 kSaveFPRegs, 4845 kSaveFPRegs,
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
5232 5342
5233 5343
5234 void LCodeGen::DoValueOf(LValueOf* instr) { 5344 void LCodeGen::DoValueOf(LValueOf* instr) {
5235 Register input = ToRegister(instr->value()); 5345 Register input = ToRegister(instr->value());
5236 Register result = ToRegister(instr->result()); 5346 Register result = ToRegister(instr->result());
5237 Register scratch = ToRegister(instr->temp()); 5347 Register scratch = ToRegister(instr->temp());
5238 Label done; 5348 Label done;
5239 5349
5240 ASSERT(input.Is(result)); 5350 ASSERT(input.Is(result));
5241 5351
5242 // If the object is a smi return it. 5352 if (!instr->hydrogen()->value()->IsHeapObject()) {
5243 __ JumpIfSmi(input, &done); 5353 // If the object is a smi return it.
5354 __ JumpIfSmi(input, &done);
5355 }
5244 5356
5245 // If the object is not a value type, return the object, otherwise 5357 // If the object is not a value type, return the object, otherwise
5246 // return the value. 5358 // return the value.
5247 __ JumpIfNotObjectType(input, scratch, scratch, JS_VALUE_TYPE, &done); 5359 __ JumpIfNotObjectType(input, scratch, scratch, JS_VALUE_TYPE, &done);
5248 __ Ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); 5360 __ Ldr(result, FieldMemOperand(input, JSValue::kValueOffset));
5249 5361
5250 __ Bind(&done); 5362 __ Bind(&done);
5251 } 5363 }
5252 5364
5253 5365
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
5329 __ Bind(&out_of_object); 5441 __ Bind(&out_of_object);
5330 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); 5442 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
5331 // Index is equal to negated out of object property index plus 1. 5443 // Index is equal to negated out of object property index plus 1.
5332 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); 5444 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2));
5333 __ Ldr(result, FieldMemOperand(result, 5445 __ Ldr(result, FieldMemOperand(result,
5334 FixedArray::kHeaderSize - kPointerSize)); 5446 FixedArray::kHeaderSize - kPointerSize));
5335 __ Bind(&done); 5447 __ Bind(&done);
5336 } 5448 }
5337 5449
5338 } } // namespace v8::internal 5450 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/a64/lithium-codegen-a64.h ('k') | src/a64/macro-assembler-a64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698