Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1 | // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "src/v8.h" |
| 6 | |
| 7 | #if V8_TARGET_ARCH_X87 |
| 8 | |
| 9 | #include "src/ic/ic.h" |
| 10 | #include "src/ic/ic-compiler.h" |
| 11 | |
| 12 | namespace v8 { |
| 13 | namespace internal { |
| 14 | |
| 15 | #define __ ACCESS_MASM(masm) |
| 16 | |
| 17 | |
| 18 | void PropertyICCompiler::GenerateRuntimeSetProperty(MacroAssembler* masm, |
| 19 | StrictMode strict_mode) { |
| 20 | // Return address is on the stack. |
| 21 | DCHECK(!ebx.is(StoreDescriptor::ReceiverRegister()) && |
| 22 | !ebx.is(StoreDescriptor::NameRegister()) && |
| 23 | !ebx.is(StoreDescriptor::ValueRegister())); |
| 24 | __ pop(ebx); |
| 25 | __ push(StoreDescriptor::ReceiverRegister()); |
| 26 | __ push(StoreDescriptor::NameRegister()); |
| 27 | __ push(StoreDescriptor::ValueRegister()); |
| 28 | __ push(Immediate(Smi::FromInt(strict_mode))); |
| 29 | __ push(ebx); // return address |
| 30 | |
| 31 | // Do tail-call to runtime routine. |
| 32 | __ TailCallRuntime(Runtime::kSetProperty, 4, 1); |
| 33 | } |
| 34 | |
| 35 | |
| 36 | #undef __ |
| 37 | #define __ ACCESS_MASM(masm()) |
| 38 | |
| 39 | Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
| 40 | CodeHandleList* handlers, |
| 41 | Handle<Name> name, |
| 42 | Code::StubType type, |
| 43 | IcCheckType check) { |
| 44 | Label miss; |
| 45 | |
| 46 | if (check == PROPERTY && |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 47 | (kind() == Code::KEYED_STORE_IC || kind() == Code::KEYED_LOAD_IC)) { |
| 48 | // In case we are compiling an IC for dictionary loads or stores, just |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 49 | // check whether the name is unique. |
| 50 | if (name.is_identical_to(isolate()->factory()->normal_ic_symbol())) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 51 | // Keyed loads with dictionaries shouldn't be here, they go generic. |
| 52 | // The DCHECK is to protect assumptions when --vector-ics is on. |
| 53 | DCHECK(kind() != Code::KEYED_LOAD_IC); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 54 | Register tmp = scratch1(); |
| 55 | __ JumpIfSmi(this->name(), &miss); |
| 56 | __ mov(tmp, FieldOperand(this->name(), HeapObject::kMapOffset)); |
| 57 | __ movzx_b(tmp, FieldOperand(tmp, Map::kInstanceTypeOffset)); |
| 58 | __ JumpIfNotUniqueNameInstanceType(tmp, &miss); |
| 59 | } else { |
| 60 | __ cmp(this->name(), Immediate(name)); |
| 61 | __ j(not_equal, &miss); |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | Label number_case; |
| 66 | Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |
| 67 | __ JumpIfSmi(receiver(), smi_target); |
| 68 | |
| 69 | // Polymorphic keyed stores may use the map register |
| 70 | Register map_reg = scratch1(); |
| 71 | DCHECK(kind() != Code::KEYED_STORE_IC || |
| 72 | map_reg.is(ElementTransitionAndStoreDescriptor::MapRegister())); |
| 73 | __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); |
| 74 | int receiver_count = types->length(); |
| 75 | int number_of_handled_maps = 0; |
| 76 | for (int current = 0; current < receiver_count; ++current) { |
| 77 | Handle<HeapType> type = types->at(current); |
| 78 | Handle<Map> map = IC::TypeToMap(*type, isolate()); |
| 79 | if (!map->is_deprecated()) { |
| 80 | number_of_handled_maps++; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 81 | Handle<WeakCell> cell = Map::WeakCellForMap(map); |
| 82 | __ CmpWeakValue(map_reg, cell, scratch2()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 83 | if (type->Is(HeapType::Number())) { |
| 84 | DCHECK(!number_case.is_unused()); |
| 85 | __ bind(&number_case); |
| 86 | } |
| 87 | __ j(equal, handlers->at(current)); |
| 88 | } |
| 89 | } |
| 90 | DCHECK(number_of_handled_maps != 0); |
| 91 | |
| 92 | __ bind(&miss); |
| 93 | TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 94 | |
| 95 | // Return the generated code. |
| 96 | InlineCacheState state = |
| 97 | number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; |
| 98 | return GetCode(kind(), type, name, state); |
| 99 | } |
| 100 | |
| 101 | |
| 102 | Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( |
| 103 | MapHandleList* receiver_maps, CodeHandleList* handler_stubs, |
| 104 | MapHandleList* transitioned_maps) { |
| 105 | Label miss; |
| 106 | __ JumpIfSmi(receiver(), &miss, Label::kNear); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 107 | Register map_reg = scratch1(); |
| 108 | __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 109 | for (int i = 0; i < receiver_maps->length(); ++i) { |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 110 | Handle<WeakCell> cell = Map::WeakCellForMap(receiver_maps->at(i)); |
| 111 | __ CmpWeakValue(map_reg, cell, scratch2()); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 112 | if (transitioned_maps->at(i).is_null()) { |
| 113 | __ j(equal, handler_stubs->at(i)); |
| 114 | } else { |
| 115 | Label next_map; |
| 116 | __ j(not_equal, &next_map, Label::kNear); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 117 | Handle<WeakCell> cell = Map::WeakCellForMap(transitioned_maps->at(i)); |
| 118 | __ LoadWeakValue(transition_map(), cell, &miss); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 119 | __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
| 120 | __ bind(&next_map); |
| 121 | } |
| 122 | } |
| 123 | __ bind(&miss); |
| 124 | TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 125 | |
| 126 | // Return the generated code. |
| 127 | return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
| 128 | } |
| 129 | |
| 130 | |
| 131 | #undef __ |
| 132 | } |
| 133 | } // namespace v8::internal |
| 134 | |
| 135 | #endif // V8_TARGET_ARCH_X87 |