OLD | NEW |
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 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 } | 426 } |
427 } | 427 } |
428 | 428 |
429 | 429 |
430 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 430 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
431 ASSERT(ToRegister(instr->context()).is(cp)); | 431 ASSERT(ToRegister(instr->context()).is(cp)); |
432 ASSERT(ToRegister(instr->function()).Is(x1)); | 432 ASSERT(ToRegister(instr->function()).Is(x1)); |
433 ASSERT(ToRegister(instr->result()).Is(x0)); | 433 ASSERT(ToRegister(instr->result()).Is(x0)); |
434 | 434 |
435 int arity = instr->arity(); | 435 int arity = instr->arity(); |
436 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 436 CallFunctionStub stub(arity, instr->hydrogen()->function_flags()); |
437 if (instr->hydrogen()->IsTailCall()) { | 437 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
438 if (NeedsEagerFrame()) { | |
439 __ Mov(masm()->StackPointer(), fp); | |
440 } | |
441 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | |
442 } else { | |
443 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
444 } | |
445 } | 438 } |
446 | 439 |
447 | 440 |
448 void LCodeGen::DoCallNew(LCallNew* instr) { | 441 void LCodeGen::DoCallNew(LCallNew* instr) { |
449 ASSERT(ToRegister(instr->context()).is(cp)); | 442 ASSERT(ToRegister(instr->context()).is(cp)); |
450 ASSERT(instr->IsMarkedAsCall()); | 443 ASSERT(instr->IsMarkedAsCall()); |
451 ASSERT(ToRegister(instr->constructor()).is(x1)); | 444 ASSERT(ToRegister(instr->constructor()).is(x1)); |
452 | 445 |
453 __ Mov(x0, instr->arity()); | 446 __ Mov(x0, instr->arity()); |
454 // No cell in x2 for construct type feedback in optimized code. | 447 // No cell in x2 for construct type feedback in optimized code. |
(...skipping 2261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2716 void LCodeGen::DoDummy(LDummy* instr) { | 2709 void LCodeGen::DoDummy(LDummy* instr) { |
2717 // Nothing to see here, move on! | 2710 // Nothing to see here, move on! |
2718 } | 2711 } |
2719 | 2712 |
2720 | 2713 |
2721 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 2714 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
2722 // Nothing to see here, move on! | 2715 // Nothing to see here, move on! |
2723 } | 2716 } |
2724 | 2717 |
2725 | 2718 |
2726 void LCodeGen::DoElementsKind(LElementsKind* instr) { | |
2727 Register result = ToRegister(instr->result()); | |
2728 Register input = ToRegister(instr->value()); | |
2729 | |
2730 // Load map into result. | |
2731 __ Ldr(result, FieldMemOperand(input, HeapObject::kMapOffset)); | |
2732 | |
2733 // Load the map's "bit field 2" into result. | |
2734 ASSERT((Map::kElementsKindBitCount + Map::kElementsKindShift) <= kByteSize); | |
2735 __ Ldrb(result.W(), FieldMemOperand(result, Map::kBitField2Offset)); | |
2736 | |
2737 // Retrieve elements_kind from bit field 2. | |
2738 __ Ubfx(result.W(), result.W(), Map::kElementsKindShift, | |
2739 Map::kElementsKindBitCount); | |
2740 } | |
2741 | |
2742 | |
2743 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 2719 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
2744 ASSERT(ToRegister(instr->context()).is(cp)); | 2720 ASSERT(ToRegister(instr->context()).is(cp)); |
2745 // FunctionLiteral instruction is marked as call, we can trash any register. | 2721 // FunctionLiteral instruction is marked as call, we can trash any register. |
2746 ASSERT(instr->IsMarkedAsCall()); | 2722 ASSERT(instr->IsMarkedAsCall()); |
2747 | 2723 |
2748 // Use the fast case closure allocation code that allocates in new | 2724 // Use the fast case closure allocation code that allocates in new |
2749 // space for nested functions that don't need literals cloning. | 2725 // space for nested functions that don't need literals cloning. |
2750 bool pretenure = instr->hydrogen()->pretenure(); | 2726 bool pretenure = instr->hydrogen()->pretenure(); |
2751 if (!pretenure && instr->hydrogen()->has_no_literals()) { | 2727 if (!pretenure && instr->hydrogen()->has_no_literals()) { |
2752 FastNewClosureStub stub(instr->hydrogen()->language_mode(), | 2728 FastNewClosureStub stub(instr->hydrogen()->language_mode(), |
(...skipping 2300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5053 return; | 5029 return; |
5054 } | 5030 } |
5055 | 5031 |
5056 Handle<Map> transition = instr->transition(); | 5032 Handle<Map> transition = instr->transition(); |
5057 | 5033 |
5058 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 5034 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
5059 Register value = ToRegister(instr->value()); | 5035 Register value = ToRegister(instr->value()); |
5060 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 5036 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
5061 DeoptimizeIfSmi(value, instr->environment()); | 5037 DeoptimizeIfSmi(value, instr->environment()); |
5062 } | 5038 } |
5063 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 5039 } else if (representation.IsDouble()) { |
5064 ASSERT(transition.is_null()); | 5040 ASSERT(transition.is_null()); |
5065 ASSERT(access.IsInobject()); | 5041 ASSERT(access.IsInobject()); |
5066 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 5042 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
5067 FPRegister value = ToDoubleRegister(instr->value()); | 5043 FPRegister value = ToDoubleRegister(instr->value()); |
5068 __ Str(value, FieldMemOperand(object, offset)); | 5044 __ Str(value, FieldMemOperand(object, offset)); |
5069 return; | 5045 return; |
5070 } | 5046 } |
5071 | 5047 |
5072 if (!transition.is_null()) { | 5048 if (!transition.is_null()) { |
5073 // Store the new map value. | 5049 // Store the new map value. |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5435 __ Push(x1, x0); | 5411 __ Push(x1, x0); |
5436 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); | 5412 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); |
5437 __ Pop(x1); | 5413 __ Pop(x1); |
5438 | 5414 |
5439 __ Bind(&allocated); | 5415 __ Bind(&allocated); |
5440 // Copy the content into the newly allocated memory. | 5416 // Copy the content into the newly allocated memory. |
5441 __ CopyFields(x0, x1, CPURegList(x10, x11, x12), size / kPointerSize); | 5417 __ CopyFields(x0, x1, CPURegList(x10, x11, x12), size / kPointerSize); |
5442 } | 5418 } |
5443 | 5419 |
5444 | 5420 |
5445 void LCodeGen::DoThrow(LThrow* instr) { | |
5446 ASSERT(ToRegister(instr->context()).is(cp)); | |
5447 Register value = ToRegister(instr->value()); | |
5448 __ Push(value); | |
5449 CallRuntime(Runtime::kThrow, 1, instr); | |
5450 | |
5451 if (FLAG_debug_code) { | |
5452 __ Unreachable(); | |
5453 } | |
5454 } | |
5455 | |
5456 | |
5457 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 5421 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
5458 Register object = ToRegister(instr->object()); | 5422 Register object = ToRegister(instr->object()); |
5459 Register temp1 = ToRegister(instr->temp1()); | 5423 Register temp1 = ToRegister(instr->temp1()); |
5460 | 5424 |
5461 Handle<Map> from_map = instr->original_map(); | 5425 Handle<Map> from_map = instr->original_map(); |
5462 Handle<Map> to_map = instr->transitioned_map(); | 5426 Handle<Map> to_map = instr->transitioned_map(); |
5463 ElementsKind from_kind = instr->from_kind(); | 5427 ElementsKind from_kind = instr->from_kind(); |
5464 ElementsKind to_kind = instr->to_kind(); | 5428 ElementsKind to_kind = instr->to_kind(); |
5465 | 5429 |
5466 Label not_applicable; | 5430 Label not_applicable; |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5620 !instr->hydrogen()->value()->range()->IsInSmiRange() || | 5584 !instr->hydrogen()->value()->range()->IsInSmiRange() || |
5621 instr->hydrogen()->value()->range()->upper() == kMaxInt) { | 5585 instr->hydrogen()->value()->range()->upper() == kMaxInt) { |
5622 // The Range class can't express upper bounds in the (kMaxInt, kMaxUint32] | 5586 // The Range class can't express upper bounds in the (kMaxInt, kMaxUint32] |
5623 // interval, so we treat kMaxInt as a sentinel for this entire interval. | 5587 // interval, so we treat kMaxInt as a sentinel for this entire interval. |
5624 DeoptimizeIfNegative(value.W(), instr->environment()); | 5588 DeoptimizeIfNegative(value.W(), instr->environment()); |
5625 } | 5589 } |
5626 __ SmiTag(result, value); | 5590 __ SmiTag(result, value); |
5627 } | 5591 } |
5628 | 5592 |
5629 | 5593 |
5630 void LCodeGen::DoValueOf(LValueOf* instr) { | |
5631 Register input = ToRegister(instr->value()); | |
5632 Register result = ToRegister(instr->result()); | |
5633 Register scratch = ToRegister(instr->temp()); | |
5634 Label done; | |
5635 | |
5636 ASSERT(input.Is(result)); | |
5637 | |
5638 if (!instr->hydrogen()->value()->IsHeapObject()) { | |
5639 // If the object is a smi return it. | |
5640 __ JumpIfSmi(input, &done); | |
5641 } | |
5642 | |
5643 // If the object is not a value type, return the object, otherwise | |
5644 // return the value. | |
5645 __ JumpIfNotObjectType(input, scratch, scratch, JS_VALUE_TYPE, &done); | |
5646 __ Ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); | |
5647 | |
5648 __ Bind(&done); | |
5649 } | |
5650 | |
5651 | |
5652 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { | 5594 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { |
5653 Register object = ToRegister(instr->value()); | 5595 Register object = ToRegister(instr->value()); |
5654 Register map = ToRegister(instr->map()); | 5596 Register map = ToRegister(instr->map()); |
5655 Register temp = ToRegister(instr->temp()); | 5597 Register temp = ToRegister(instr->temp()); |
5656 __ Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset)); | 5598 __ Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset)); |
5657 __ Cmp(map, temp); | 5599 __ Cmp(map, temp); |
5658 DeoptimizeIf(ne, instr->environment()); | 5600 DeoptimizeIf(ne, instr->environment()); |
5659 } | 5601 } |
5660 | 5602 |
5661 | 5603 |
5662 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { | 5604 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
5663 Register receiver = ToRegister(instr->receiver()); | 5605 Register receiver = ToRegister(instr->receiver()); |
5664 Register function = ToRegister(instr->function()); | 5606 Register function = ToRegister(instr->function()); |
5665 Register result = ToRegister(instr->result()); | 5607 Register result = ToRegister(instr->result()); |
5666 | 5608 |
5667 // If the receiver is null or undefined, we have to pass the global object as | 5609 // If the receiver is null or undefined, we have to pass the global object as |
5668 // a receiver to normal functions. Values have to be passed unchanged to | 5610 // a receiver to normal functions. Values have to be passed unchanged to |
5669 // builtins and strict-mode functions. | 5611 // builtins and strict-mode functions. |
5670 Label global_object, done, deopt; | 5612 Label global_object, done, deopt; |
5671 | 5613 |
5672 __ Ldr(result, FieldMemOperand(function, | 5614 if (!instr->hydrogen()->known_function()) { |
5673 JSFunction::kSharedFunctionInfoOffset)); | 5615 __ Ldr(result, FieldMemOperand(function, |
| 5616 JSFunction::kSharedFunctionInfoOffset)); |
5674 | 5617 |
5675 // CompilerHints is an int32 field. See objects.h. | 5618 // CompilerHints is an int32 field. See objects.h. |
5676 __ Ldr(result.W(), | 5619 __ Ldr(result.W(), |
5677 FieldMemOperand(result, SharedFunctionInfo::kCompilerHintsOffset)); | 5620 FieldMemOperand(result, SharedFunctionInfo::kCompilerHintsOffset)); |
5678 | 5621 |
5679 // Do not transform the receiver to object for strict mode functions. | 5622 // Do not transform the receiver to object for strict mode functions. |
5680 __ Tbnz(result, SharedFunctionInfo::kStrictModeFunction, &done); | 5623 __ Tbnz(result, SharedFunctionInfo::kStrictModeFunction, &done); |
5681 | 5624 |
5682 // Do not transform the receiver to object for builtins. | 5625 // Do not transform the receiver to object for builtins. |
5683 __ Tbnz(result, SharedFunctionInfo::kNative, &done); | 5626 __ Tbnz(result, SharedFunctionInfo::kNative, &done); |
| 5627 } |
5684 | 5628 |
5685 // Normal function. Replace undefined or null with global receiver. | 5629 // Normal function. Replace undefined or null with global receiver. |
5686 __ JumpIfRoot(receiver, Heap::kNullValueRootIndex, &global_object); | 5630 __ JumpIfRoot(receiver, Heap::kNullValueRootIndex, &global_object); |
5687 __ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex, &global_object); | 5631 __ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex, &global_object); |
5688 | 5632 |
5689 // Deoptimize if the receiver is not a JS object. | 5633 // Deoptimize if the receiver is not a JS object. |
5690 __ JumpIfSmi(receiver, &deopt); | 5634 __ JumpIfSmi(receiver, &deopt); |
5691 __ CompareObjectType(receiver, result, result, FIRST_SPEC_OBJECT_TYPE); | 5635 __ CompareObjectType(receiver, result, result, FIRST_SPEC_OBJECT_TYPE); |
5692 __ B(ge, &done); | 5636 __ B(ge, &done); |
5693 // Otherwise, fall through to deopt. | 5637 // Otherwise, fall through to deopt. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5729 __ Bind(&out_of_object); | 5673 __ Bind(&out_of_object); |
5730 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 5674 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
5731 // Index is equal to negated out of object property index plus 1. | 5675 // Index is equal to negated out of object property index plus 1. |
5732 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 5676 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
5733 __ Ldr(result, FieldMemOperand(result, | 5677 __ Ldr(result, FieldMemOperand(result, |
5734 FixedArray::kHeaderSize - kPointerSize)); | 5678 FixedArray::kHeaderSize - kPointerSize)); |
5735 __ Bind(&done); | 5679 __ Bind(&done); |
5736 } | 5680 } |
5737 | 5681 |
5738 } } // namespace v8::internal | 5682 } } // namespace v8::internal |
OLD | NEW |