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

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

Issue 148573005: A64: Synchronize with r16249. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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/stub-cache-a64.cc » ('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 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 208
209 virtual void EmitInverted(Label* label) const { 209 virtual void EmitInverted(Label* label) const {
210 __ JumpIfNotHeapNumber(value_, label); 210 __ JumpIfNotHeapNumber(value_, label);
211 } 211 }
212 212
213 private: 213 private:
214 const Register& value_; 214 const Register& value_;
215 }; 215 };
216 216
217 217
218 // Test the input and branch if it is the specified root value.
219 class BranchIfRoot : public BranchGenerator {
220 public:
221 BranchIfRoot(LCodeGen* codegen, const Register& value,
222 Heap::RootListIndex index)
223 : BranchGenerator(codegen), value_(value), index_(index) { }
224
225 virtual void Emit(Label* label) const {
226 __ JumpIfRoot(value_, index_, label);
227 }
228
229 virtual void EmitInverted(Label* label) const {
230 __ JumpIfNotRoot(value_, index_, label);
231 }
232
233 private:
234 const Register& value_;
235 const Heap::RootListIndex index_;
236 };
237
238
218 void LCodeGen::WriteTranslation(LEnvironment* environment, 239 void LCodeGen::WriteTranslation(LEnvironment* environment,
219 Translation* translation) { 240 Translation* translation) {
220 if (environment == NULL) return; 241 if (environment == NULL) return;
221 242
222 // The translation includes one command per value in the environment. 243 // The translation includes one command per value in the environment.
223 int translation_size = environment->translation_size(); 244 int translation_size = environment->translation_size();
224 // The output frame height does not include the parameters. 245 // The output frame height does not include the parameters.
225 int height = translation_size - environment->parameter_count(); 246 int height = translation_size - environment->parameter_count();
226 247
227 WriteTranslation(environment->outer(), translation); 248 WriteTranslation(environment->outer(), translation);
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 583
563 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { 584 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) {
564 LPointerMap empty_pointers(RelocInfo::kNoPosition, zone()); 585 LPointerMap empty_pointers(RelocInfo::kNoPosition, zone());
565 RecordSafepoint(&empty_pointers, deopt_mode); 586 RecordSafepoint(&empty_pointers, deopt_mode);
566 } 587 }
567 588
568 589
569 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 590 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
570 int arguments, 591 int arguments,
571 Safepoint::DeoptMode deopt_mode) { 592 Safepoint::DeoptMode deopt_mode) {
572 RecordSafepoint( 593 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
573 pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
574 } 594 }
575 595
576 596
597 void LCodeGen::RecordSafepointWithRegistersAndDoubles(
598 LPointerMap* pointers, int arguments, Safepoint::DeoptMode deopt_mode) {
599 RecordSafepoint(
600 pointers, Safepoint::kWithRegistersAndDoubles, arguments, deopt_mode);
601 }
602
603
577 bool LCodeGen::GenerateCode() { 604 bool LCodeGen::GenerateCode() {
578 LPhase phase("Z_Code generation", chunk()); 605 LPhase phase("Z_Code generation", chunk());
579 ASSERT(is_unused()); 606 ASSERT(is_unused());
580 status_ = GENERATING; 607 status_ = GENERATING;
581 608
582 // Open a frame scope to indicate that there is a frame on the stack. The 609 // Open a frame scope to indicate that there is a frame on the stack. The
583 // NONE indicates that the scope shouldn't actually generate code to set up 610 // NONE indicates that the scope shouldn't actually generate code to set up
584 // the frame (that is done in GeneratePrologue). 611 // the frame (that is done in GeneratePrologue).
585 FrameScope frame_scope(masm_, StackFrame::NONE); 612 FrameScope frame_scope(masm_, StackFrame::NONE);
586 613
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after
1286 1313
1287 1314
1288 template<class InstrType> 1315 template<class InstrType>
1289 void LCodeGen::EmitBranchIfHeapNumber(InstrType instr, 1316 void LCodeGen::EmitBranchIfHeapNumber(InstrType instr,
1290 const Register& value) { 1317 const Register& value) {
1291 BranchIfHeapNumber branch(this, value); 1318 BranchIfHeapNumber branch(this, value);
1292 EmitBranchGeneric(instr, branch); 1319 EmitBranchGeneric(instr, branch);
1293 } 1320 }
1294 1321
1295 1322
1323 template<class InstrType>
1324 void LCodeGen::EmitBranchIfRoot(InstrType instr,
1325 const Register& value,
1326 Heap::RootListIndex index) {
1327 BranchIfRoot branch(this, value, index);
1328 EmitBranchGeneric(instr, branch);
1329 }
1330
1331
1296 void LCodeGen::DoGap(LGap* gap) { 1332 void LCodeGen::DoGap(LGap* gap) {
1297 for (int i = LGap::FIRST_INNER_POSITION; 1333 for (int i = LGap::FIRST_INNER_POSITION;
1298 i <= LGap::LAST_INNER_POSITION; 1334 i <= LGap::LAST_INNER_POSITION;
1299 i++) { 1335 i++) {
1300 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); 1336 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
1301 LParallelMove* move = gap->GetParallelMove(inner_pos); 1337 LParallelMove* move = gap->GetParallelMove(inner_pos);
1302 if (move != NULL) { 1338 if (move != NULL) {
1303 resolver_.Resolve(move); 1339 resolver_.Resolve(move);
1304 } 1340 }
1305 } 1341 }
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after
2219 // The class name we are testing against is internalized since it's a literal. 2255 // The class name we are testing against is internalized since it's a literal.
2220 // The name in the constructor is internalized because of the way the context 2256 // The name in the constructor is internalized because of the way the context
2221 // is booted. This routine isn't expected to work for random API-created 2257 // is booted. This routine isn't expected to work for random API-created
2222 // classes and it doesn't have to because you can't access it with natives 2258 // classes and it doesn't have to because you can't access it with natives
2223 // syntax. Since both sides are internalized it is sufficient to use an 2259 // syntax. Since both sides are internalized it is sufficient to use an
2224 // identity comparison. 2260 // identity comparison.
2225 EmitCompareAndBranch(instr, eq, scratch1, Operand(class_name)); 2261 EmitCompareAndBranch(instr, eq, scratch1, Operand(class_name));
2226 } 2262 }
2227 2263
2228 2264
2265 void LCodeGen::DoCmpHoleAndBranchD(LCmpHoleAndBranchD* instr) {
2266 ASSERT(instr->hydrogen()->representation().IsDouble());
2267 FPRegister object = ToDoubleRegister(instr->object());
2268 Register temp = ToRegister(instr->temp());
2269
2270 // If we don't have a NaN, we don't have the hole, so branch now to avoid the
2271 // (relatively expensive) hole-NaN check.
2272 __ Fcmp(object, object);
2273 __ B(vc, instr->FalseLabel(chunk_));
2274
2275 // We have a NaN, but is it the hole?
2276 __ Fmov(temp, object);
2277 EmitCompareAndBranch(instr, eq, temp, kHoleNanInt64);
2278 }
2279
2280
2281 void LCodeGen::DoCmpHoleAndBranchT(LCmpHoleAndBranchT* instr) {
2282 ASSERT(instr->hydrogen()->representation().IsTagged());
2283 Register object = ToRegister(instr->object());
2284
2285 EmitBranchIfRoot(instr, object, Heap::kTheHoleValueRootIndex);
2286 }
2287
2288
2229 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { 2289 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
2230 Register value = ToRegister(instr->value()); 2290 Register value = ToRegister(instr->value());
2231 Register map = ToRegister(instr->temp()); 2291 Register map = ToRegister(instr->temp());
2232 2292
2233 __ Ldr(map, FieldMemOperand(value, HeapObject::kMapOffset)); 2293 __ Ldr(map, FieldMemOperand(value, HeapObject::kMapOffset));
2234 EmitCompareAndBranch(instr, eq, map, Operand(instr->map())); 2294 EmitCompareAndBranch(instr, eq, map, Operand(instr->map()));
2235 } 2295 }
2236 2296
2237 2297
2238 void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) { 2298 void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
2375 } 2435 }
2376 } 2436 }
2377 2437
2378 2438
2379 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { 2439 void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
2380 Register reg = ToRegister(instr->value()); 2440 Register reg = ToRegister(instr->value());
2381 Handle<JSFunction> target = instr->hydrogen()->target(); 2441 Handle<JSFunction> target = instr->hydrogen()->target();
2382 AllowDeferredHandleDereference smi_check; 2442 AllowDeferredHandleDereference smi_check;
2383 if (isolate()->heap()->InNewSpace(*target)) { 2443 if (isolate()->heap()->InNewSpace(*target)) {
2384 Register temp = ToRegister(instr->temp()); 2444 Register temp = ToRegister(instr->temp());
2385 Handle<Cell> cell = isolate()->factory()->NewPropertyCell(target); 2445 Handle<Cell> cell = isolate()->factory()->NewCell(target);
2386 __ Mov(temp, Operand(Handle<Object>(cell))); 2446 __ Mov(temp, Operand(Handle<Object>(cell)));
2387 __ Ldr(temp, FieldMemOperand(temp, Cell::kValueOffset)); 2447 __ Ldr(temp, FieldMemOperand(temp, Cell::kValueOffset));
2388 __ Cmp(reg, temp); 2448 __ Cmp(reg, temp);
2389 } else { 2449 } else {
2390 __ Cmp(reg, Operand(target)); 2450 __ Cmp(reg, Operand(target));
2391 } 2451 }
2392 DeoptimizeIf(ne, instr->environment()); 2452 DeoptimizeIf(ne, instr->environment());
2393 } 2453 }
2394 2454
2395 2455
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2448 2508
2449 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { 2509 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
2450 Deoptimizer::BailoutType type = instr->hydrogen()->type(); 2510 Deoptimizer::BailoutType type = instr->hydrogen()->type();
2451 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the 2511 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
2452 // needed return address), even though the implementation of LAZY and EAGER is 2512 // needed return address), even though the implementation of LAZY and EAGER is
2453 // now identical. When LAZY is eventually completely folded into EAGER, remove 2513 // now identical. When LAZY is eventually completely folded into EAGER, remove
2454 // the special case below. 2514 // the special case below.
2455 if (info()->IsStub() && (type == Deoptimizer::EAGER)) { 2515 if (info()->IsStub() && (type == Deoptimizer::EAGER)) {
2456 type = Deoptimizer::LAZY; 2516 type = Deoptimizer::LAZY;
2457 } 2517 }
2518
2519 Comment(";;; deoptimize: %s", instr->hydrogen()->reason());
2458 Deoptimize(instr->environment(), type); 2520 Deoptimize(instr->environment(), type);
2459 } 2521 }
2460 2522
2461 2523
2462 void LCodeGen::DoDivI(LDivI* instr) { 2524 void LCodeGen::DoDivI(LDivI* instr) {
2463 Register dividend = ToRegister32(instr->left()); 2525 Register dividend = ToRegister32(instr->left());
2464 Register result = ToRegister32(instr->result()); 2526 Register result = ToRegister32(instr->result());
2465 2527
2466 bool has_power_of_2_divisor = instr->hydrogen()->HasPowerOf2Divisor(); 2528 bool has_power_of_2_divisor = instr->hydrogen()->HasPowerOf2Divisor();
2467 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 2529 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
(...skipping 1008 matching lines...) Expand 10 before | Expand all | Expand 10 after
3476 if (access.IsInobject()) { 3538 if (access.IsInobject()) {
3477 __ Ldr(result, FieldMemOperand(object, offset)); 3539 __ Ldr(result, FieldMemOperand(object, offset));
3478 } else { 3540 } else {
3479 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); 3541 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
3480 __ Ldr(result, FieldMemOperand(result, offset)); 3542 __ Ldr(result, FieldMemOperand(result, offset));
3481 } 3543 }
3482 } 3544 }
3483 } 3545 }
3484 3546
3485 3547
3486 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
3487 Register object,
3488 Handle<Map> type,
3489 Handle<String> name,
3490 LEnvironment* env) {
3491 LookupResult lookup(isolate());
3492 type->LookupDescriptor(NULL, *name, &lookup);
3493 ASSERT(lookup.IsFound() || lookup.IsCacheable());
3494
3495 if (lookup.IsField()) {
3496 int index = lookup.GetLocalFieldIndexFromMap(*type);
3497 int offset = index * kPointerSize;
3498 if (index < 0) {
3499 // Negative property indices are in-object properties, indexed from the
3500 // end of the fixed part of the object.
3501 __ Ldr(result, FieldMemOperand(object, offset + type->instance_size()));
3502 } else {
3503 // Non-negative property indices are in the properties array.
3504 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
3505 __ Ldr(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize));
3506 }
3507 } else if (lookup.IsConstant()) {
3508 Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
3509 __ LoadObject(result, constant);
3510 } else {
3511 // Negative lookup. Check prototypes.
3512 Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
3513 Heap* heap = type->GetHeap();
3514 while (*current != heap->null_value()) {
3515 __ LoadHeapObject(result, current);
3516 __ CompareMap(result, result, Handle<Map>(current->map()));
3517 DeoptimizeIf(ne, env);
3518 current =
3519 Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
3520 }
3521 __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
3522 }
3523 }
3524
3525
3526 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
3527 Register object = ToRegister(instr->object());
3528 Register result = ToRegister(instr->result());
3529 // The result register is loaded with its value when the object's map has been
3530 // found. At this point we don't need to hold the map in object_map anymore,
3531 // so both values can share the same register.
3532 // However when we need to go through the generic code path, the instruction
3533 // is MarkedAsCall and both object and result registers will be allocated to
3534 // x0. Object should not be clobbered until the call to LoadIC. We choose a
3535 // different arbitrary register for object_map in this case.
3536 Register object_map = instr->IsMarkedAsCall()
3537 ? x10
3538 : result;
3539
3540 int map_count = instr->hydrogen()->types()->length();
3541 bool need_generic = instr->hydrogen()->need_generic();
3542
3543 if ((map_count == 0) && !need_generic) {
3544 Deoptimize(instr->environment());
3545 return;
3546 }
3547
3548 Handle<String> name = instr->hydrogen()->name();
3549 Label done;
3550 __ Ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
3551 for (int i = 0; i < map_count; i++) {
3552 bool last = (i == (map_count - 1));
3553 Handle<Map> map = instr->hydrogen()->types()->at(i);
3554 Label check_passed;
3555 __ CompareMap(object_map, map, &check_passed);
3556 if (last && !need_generic) {
3557 DeoptimizeIf(ne, instr->environment());
3558 __ Bind(&check_passed);
3559 EmitLoadFieldOrConstantFunction(result, object, map, name,
3560 instr->environment());
3561 } else {
3562 Label next;
3563 __ B(ne, &next);
3564 __ Bind(&check_passed);
3565 EmitLoadFieldOrConstantFunction(result, object, map, name,
3566 instr->environment());
3567 __ B(&done);
3568 __ Bind(&next);
3569 }
3570 }
3571 if (need_generic) {
3572 ASSERT(instr->IsMarkedAsCall());
3573 // LoadIC expects x2 to hold the name, and x0 to hold the receiver.
3574 ASSERT(object.Is(x0));
3575 __ Mov(x2, Operand(name));
3576 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
3577 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3578 }
3579 __ Bind(&done);
3580 }
3581
3582
3583 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { 3548 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
3584 // LoadIC expects x2 to hold the name, and x0 to hold the receiver. 3549 // LoadIC expects x2 to hold the name, and x0 to hold the receiver.
3585 ASSERT(ToRegister(instr->object()).is(x0)); 3550 ASSERT(ToRegister(instr->object()).is(x0));
3586 __ Mov(x2, Operand(instr->name())); 3551 __ Mov(x2, Operand(instr->name()));
3587 3552
3588 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 3553 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
3589 CallCode(ic, RelocInfo::CODE_TARGET, instr); 3554 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3590 3555
3591 ASSERT(ToRegister(instr->result()).is(x0)); 3556 ASSERT(ToRegister(instr->result()).is(x0));
3592 } 3557 }
(...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after
4331 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } 4296 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); }
4332 virtual LInstruction* instr() { return instr_; } 4297 virtual LInstruction* instr() { return instr_; }
4333 private: 4298 private:
4334 LNumberTagD* instr_; 4299 LNumberTagD* instr_;
4335 }; 4300 };
4336 4301
4337 DoubleRegister input = ToDoubleRegister(instr->value()); 4302 DoubleRegister input = ToDoubleRegister(instr->value());
4338 Register result = ToRegister(instr->result()); 4303 Register result = ToRegister(instr->result());
4339 Register temp1 = ToRegister(instr->temp1()); 4304 Register temp1 = ToRegister(instr->temp1());
4340 Register temp2 = ToRegister(instr->temp2()); 4305 Register temp2 = ToRegister(instr->temp2());
4341 Label done;
4342
4343 bool convert_hole = false;
4344 HValue* change_input = instr->hydrogen()->value();
4345 if (change_input->IsLoadKeyed()) {
4346 HLoadKeyed* load = HLoadKeyed::cast(change_input);
4347 convert_hole = load->UsesMustHandleHole();
4348 }
4349
4350 if (convert_hole) {
4351 Label no_special_nan_handling, canonicalize;
4352 // TODO(jbramley): This special case does not exist in bleeding_edge.
4353 // * Non-NaN inputs are handled as usual.
4354 // * If the input is the hole, the output is the hole.
4355 // * If the input is any other NaN, the output is the canonical NaN.
4356 __ Fcmp(input, 0.0);
4357 __ B(vc, &no_special_nan_handling);
4358 __ Fmov(temp1, input);
4359 __ Cmp(temp1, kHoleNanInt64);
4360 __ B(ne, &canonicalize);
4361 __ Mov(result, Operand(factory()->the_hole_value()));
4362 __ B(&done);
4363 __ Bind(&canonicalize);
4364 // TODO(jbramley): Overwriting the input is probably a mistake, but this
4365 // code is removed in bleeding_edge anyway so it won't be here for long.
4366 TODO_UNIMPLEMENTED("DoNumberTagD: Fix NaN canonicalization logic.");
4367 __ Fmov(input, FixedDoubleArray::canonical_not_the_hole_nan_as_double());
4368 __ Bind(&no_special_nan_handling);
4369 }
4370 4306
4371 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); 4307 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
4372 if (FLAG_inline_new) { 4308 if (FLAG_inline_new) {
4373 __ AllocateHeapNumber(result, deferred->entry(), temp1, temp2); 4309 __ AllocateHeapNumber(result, deferred->entry(), temp1, temp2);
4374 } else { 4310 } else {
4375 __ B(deferred->entry()); 4311 __ B(deferred->entry());
4376 } 4312 }
4377 4313
4378 __ Bind(deferred->exit()); 4314 __ Bind(deferred->exit());
4379 __ Str(input, FieldMemOperand(result, HeapNumber::kValueOffset)); 4315 __ Str(input, FieldMemOperand(result, HeapNumber::kValueOffset));
4380 __ Bind(&done);
4381 } 4316 }
4382 4317
4383 4318
4384 void LCodeGen::DoDeferredNumberTagU(LInstruction* instr, 4319 void LCodeGen::DoDeferredNumberTagU(LInstruction* instr,
4385 LOperand* value, 4320 LOperand* value,
4386 LOperand* temp1, 4321 LOperand* temp1,
4387 LOperand* temp2) { 4322 LOperand* temp2) {
4388 Label slow, convert_and_store; 4323 Label slow, convert_and_store;
4389 Register src = ToRegister32(value); 4324 Register src = ToRegister32(value);
4390 Register dst = ToRegister(instr->result()); 4325 Register dst = ToRegister(instr->result());
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
4453 __ B(hi, deferred->entry()); 4388 __ B(hi, deferred->entry());
4454 __ SmiTag(result, value); 4389 __ SmiTag(result, value);
4455 __ Bind(deferred->exit()); 4390 __ Bind(deferred->exit());
4456 } 4391 }
4457 4392
4458 4393
4459 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { 4394 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
4460 Register input = ToRegister(instr->value()); 4395 Register input = ToRegister(instr->value());
4461 Register scratch = ToRegister(instr->temp()); 4396 Register scratch = ToRegister(instr->temp());
4462 DoubleRegister result = ToDoubleRegister(instr->result()); 4397 DoubleRegister result = ToDoubleRegister(instr->result());
4463 bool allow_undefined_as_nan = instr->hydrogen()->allow_undefined_as_nan(); 4398 bool can_convert_undefined_to_nan =
4399 instr->hydrogen()->can_convert_undefined_to_nan();
4464 4400
4465 Label done, load_smi; 4401 Label done, load_smi;
4466 4402
4467 // Work out what untag mode we're working with. 4403 // Work out what untag mode we're working with.
4468 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED;
4469 HValue* value = instr->hydrogen()->value(); 4404 HValue* value = instr->hydrogen()->value();
4470 if (value->type().IsSmi()) { 4405 NumberUntagDMode mode = value->representation().IsSmi()
4471 mode = NUMBER_CANDIDATE_IS_SMI; 4406 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
4472 } else if (value->IsLoadKeyed()) {
4473 HLoadKeyed* load = HLoadKeyed::cast(value);
4474 if (load->UsesMustHandleHole()) {
4475 if (load->hole_mode() == ALLOW_RETURN_HOLE) {
4476 mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE;
4477 }
4478 }
4479 }
4480 4407
4481 STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE > 4408 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
4482 NUMBER_CANDIDATE_IS_ANY_TAGGED);
4483 if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
4484 __ JumpIfSmi(input, &load_smi); 4409 __ JumpIfSmi(input, &load_smi);
4485 4410
4486 Label convert_undefined, deopt; 4411 Label convert_undefined, deopt;
4487 4412
4488 // Heap number map check. 4413 // Heap number map check.
4489 Label* not_heap_number = allow_undefined_as_nan ? &convert_undefined 4414 Label* not_heap_number = can_convert_undefined_to_nan ? &convert_undefined
4490 : &deopt; 4415 : &deopt;
4491 __ Ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); 4416 __ Ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
4492 __ JumpIfNotRoot(scratch, Heap::kHeapNumberMapRootIndex, not_heap_number); 4417 __ JumpIfNotRoot(scratch, Heap::kHeapNumberMapRootIndex, not_heap_number);
4493 4418
4494 // Load heap number. 4419 // Load heap number.
4495 __ Ldr(result, FieldMemOperand(input, HeapNumber::kValueOffset)); 4420 __ Ldr(result, FieldMemOperand(input, HeapNumber::kValueOffset));
4496 if (instr->hydrogen()->deoptimize_on_minus_zero()) { 4421 if (instr->hydrogen()->deoptimize_on_minus_zero()) {
4497 __ JumpIfMinusZero(result, &deopt); 4422 __ JumpIfMinusZero(result, &deopt);
4498 } 4423 }
4499 __ B(&done); 4424 __ B(&done);
4500 4425
4501 if (allow_undefined_as_nan) { 4426 if (can_convert_undefined_to_nan) {
4502 Label load_nan; 4427 __ Bind(&convert_undefined);
4428 __ JumpIfNotRoot(input, Heap::kUndefinedValueRootIndex, &deopt);
4503 4429
4504 __ Bind(&convert_undefined);
4505 // Convert undefined (and hole) to NaN.
4506 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
4507 __ JumpIfRoot(input, Heap::kUndefinedValueRootIndex, &load_nan);
4508 __ JumpIfNotRoot(input, Heap::kTheHoleValueRootIndex, &deopt);
4509 } else {
4510 ASSERT(mode == NUMBER_CANDIDATE_IS_ANY_TAGGED);
4511 __ JumpIfNotRoot(input, Heap::kUndefinedValueRootIndex, &deopt);
4512 }
4513
4514 __ Bind(&load_nan);
4515 __ LoadRoot(scratch, Heap::kNanValueRootIndex); 4430 __ LoadRoot(scratch, Heap::kNanValueRootIndex);
4516 __ Ldr(result, FieldMemOperand(scratch, HeapNumber::kValueOffset)); 4431 __ Ldr(result, FieldMemOperand(scratch, HeapNumber::kValueOffset));
4517 __ B(&done); 4432 __ B(&done);
4518 } 4433 }
4519 4434
4520 __ Bind(&deopt); 4435 __ Bind(&deopt);
4521 Deoptimize(instr->environment()); 4436 Deoptimize(instr->environment());
4522 } else { 4437 } else {
4523 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); 4438 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI);
4524 // Fall through to load_smi. 4439 // Fall through to load_smi.
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after
5420 __ CheckMap(object, temp1, from_map, &not_applicable, DONT_DO_SMI_CHECK); 5335 __ CheckMap(object, temp1, from_map, &not_applicable, DONT_DO_SMI_CHECK);
5421 5336
5422 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { 5337 if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
5423 Register new_map = ToRegister(instr->temp2()); 5338 Register new_map = ToRegister(instr->temp2());
5424 __ Mov(new_map, Operand(to_map)); 5339 __ Mov(new_map, Operand(to_map));
5425 __ Str(new_map, FieldMemOperand(object, HeapObject::kMapOffset)); 5340 __ Str(new_map, FieldMemOperand(object, HeapObject::kMapOffset));
5426 // Write barrier. 5341 // Write barrier.
5427 __ RecordWriteField(object, HeapObject::kMapOffset, new_map, temp1, 5342 __ RecordWriteField(object, HeapObject::kMapOffset, new_map, temp1,
5428 GetLinkRegisterState(), kDontSaveFPRegs); 5343 GetLinkRegisterState(), kDontSaveFPRegs);
5429 } else { 5344 } else {
5430 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); 5345 PushSafepointRegistersScope scope(
5346 this, Safepoint::kWithRegistersAndDoubles);
5431 __ Mov(x0, object); 5347 __ Mov(x0, object);
5432 __ Mov(x1, Operand(to_map)); 5348 __ Mov(x1, Operand(to_map));
5433 TransitionElementsKindStub stub(from_kind, to_kind); 5349 TransitionElementsKindStub stub(from_kind, to_kind);
5434 __ CallStub(&stub); 5350 __ CallStub(&stub);
5435 RecordSafepointWithRegisters( 5351 RecordSafepointWithRegistersAndDoubles(
5436 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 5352 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
5437 } 5353 }
5438 __ Bind(&not_applicable); 5354 __ Bind(&not_applicable);
5439 } 5355 }
5440 5356
5441 5357
5442 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { 5358 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
5443 Register object = ToRegister(instr->object()); 5359 Register object = ToRegister(instr->object());
5444 Register temp1 = ToRegister(instr->temp1()); 5360 Register temp1 = ToRegister(instr->temp1());
5445 Register temp2 = ToRegister(instr->temp2()); 5361 Register temp2 = ToRegister(instr->temp2());
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
5662 __ Bind(&out_of_object); 5578 __ Bind(&out_of_object);
5663 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); 5579 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
5664 // Index is equal to negated out of object property index plus 1. 5580 // Index is equal to negated out of object property index plus 1.
5665 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); 5581 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2));
5666 __ Ldr(result, FieldMemOperand(result, 5582 __ Ldr(result, FieldMemOperand(result,
5667 FixedArray::kHeaderSize - kPointerSize)); 5583 FixedArray::kHeaderSize - kPointerSize));
5668 __ Bind(&done); 5584 __ Bind(&done);
5669 } 5585 }
5670 5586
5671 } } // namespace v8::internal 5587 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/a64/lithium-codegen-a64.h ('k') | src/a64/stub-cache-a64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698