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

Side by Side Diff: src/type-info.cc

Issue 6529055: [Isolates] Merge crankshaft (r5922 from bleeding_edge). (Closed)
Patch Set: Win32 port Created 9 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
« no previous file with comments | « src/type-info.h ('k') | src/utils.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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29
30 #include "ast.h"
31 #include "compiler.h"
32 #include "ic.h"
33 #include "macro-assembler.h"
34 #include "stub-cache.h"
29 #include "type-info.h" 35 #include "type-info.h"
36
37 #include "ic-inl.h"
30 #include "objects-inl.h" 38 #include "objects-inl.h"
31 39
32 namespace v8 { 40 namespace v8 {
33 namespace internal { 41 namespace internal {
34 42
35 43
36 TypeInfo TypeInfo::TypeFromValue(Handle<Object> value) { 44 TypeInfo TypeInfo::TypeFromValue(Handle<Object> value) {
37 TypeInfo info; 45 TypeInfo info;
38 if (value->IsSmi()) { 46 if (value->IsSmi()) {
39 info = TypeInfo::Smi(); 47 info = TypeInfo::Smi();
40 } else if (value->IsHeapNumber()) { 48 } else if (value->IsHeapNumber()) {
41 info = TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value()) 49 info = TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value())
42 ? TypeInfo::Integer32() 50 ? TypeInfo::Integer32()
43 : TypeInfo::Double(); 51 : TypeInfo::Double();
44 } else if (value->IsString()) { 52 } else if (value->IsString()) {
45 info = TypeInfo::String(); 53 info = TypeInfo::String();
46 } else { 54 } else {
47 info = TypeInfo::Unknown(); 55 info = TypeInfo::Unknown();
48 } 56 }
49 return info; 57 return info;
50 } 58 }
51 59
52 60
61 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code) {
62 Initialize(code);
63 }
64
65
66 void TypeFeedbackOracle::Initialize(Handle<Code> code) {
67 Isolate* isolate = Isolate::Current();
68 ASSERT(map_.is_null()); // Only initialize once.
69 map_ = isolate->factory()->NewJSObject(isolate->object_function());
70 PopulateMap(code);
71 }
72
73
74 bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) {
75 return IsMonomorphic(expr->position());
76 }
77
78
79 bool TypeFeedbackOracle:: StoreIsMonomorphic(Assignment* expr) {
80 return IsMonomorphic(expr->position());
81 }
82
83
84 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) {
85 return IsMonomorphic(expr->position());
86 }
87
88
89 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) {
90 ASSERT(LoadIsMonomorphic(expr));
91 return Handle<Map>::cast(GetElement(map_, expr->position()));
92 }
93
94
95 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Assignment* expr) {
96 ASSERT(StoreIsMonomorphic(expr));
97 return Handle<Map>::cast(GetElement(map_, expr->position()));
98 }
99
100
101 Handle<Map> TypeFeedbackOracle::CallMonomorphicReceiverType(Call* expr) {
102 ASSERT(CallIsMonomorphic(expr));
103 return Handle<Map>::cast(GetElement(map_, expr->position()));
104 }
105
106
107 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
108 Handle<String> name) {
109 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
110 return CollectReceiverTypes(expr->position(), name, flags);
111 }
112
113
114 ZoneMapList* TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr,
115 Handle<String> name) {
116 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL);
117 return CollectReceiverTypes(expr->position(), name, flags);
118 }
119
120
121 ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr,
122 Handle<String> name) {
123 int arity = expr->arguments()->length();
124 Code::Flags flags = Code::ComputeMonomorphicFlags(
125 Code::CALL_IC, NORMAL, OWN_MAP, NOT_IN_LOOP, arity);
126 return CollectReceiverTypes(expr->position(), name, flags);
127 }
128
129
130 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
131 Handle<Object> object = GetElement(map_, expr->position());
132 return *object == Isolate::Current()->builtins()->builtin(id);
133 }
134
135
136 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr, Side side) {
137 Handle<Object> object = GetElement(map_, expr->position());
138 TypeInfo unknown = TypeInfo::Unknown();
139 if (!object->IsCode()) return unknown;
140 Handle<Code> code = Handle<Code>::cast(object);
141 if (!code->is_compare_ic_stub()) return unknown;
142
143 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
144 switch (state) {
145 case CompareIC::UNINITIALIZED:
146 case CompareIC::SMIS:
147 return TypeInfo::Smi();
148 case CompareIC::HEAP_NUMBERS:
149 return TypeInfo::Number();
150 case CompareIC::OBJECTS:
151 // TODO(kasperl): We really need a type for JS objects here.
152 return TypeInfo::NonPrimitive();
153 case CompareIC::GENERIC:
154 default:
155 return unknown;
156 }
157 }
158
159
160 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr, Side side) {
161 Handle<Object> object = GetElement(map_, expr->position());
162 TypeInfo unknown = TypeInfo::Unknown();
163 if (!object->IsCode()) return unknown;
164 Handle<Code> code = Handle<Code>::cast(object);
165 if (code->is_binary_op_stub()) {
166 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>(
167 code->binary_op_type());
168 switch (type) {
169 case BinaryOpIC::UNINIT_OR_SMI:
170 return TypeInfo::Smi();
171 case BinaryOpIC::DEFAULT:
172 return (expr->op() == Token::DIV || expr->op() == Token::MUL)
173 ? TypeInfo::Double()
174 : TypeInfo::Integer32();
175 case BinaryOpIC::HEAP_NUMBERS:
176 return TypeInfo::Double();
177 default:
178 return unknown;
179 }
180 } else if (code->is_type_recording_binary_op_stub()) {
181 TRBinaryOpIC::TypeInfo type = static_cast<TRBinaryOpIC::TypeInfo>(
182 code->type_recording_binary_op_type());
183 TRBinaryOpIC::TypeInfo result_type = static_cast<TRBinaryOpIC::TypeInfo>(
184 code->type_recording_binary_op_result_type());
185
186 switch (type) {
187 case TRBinaryOpIC::UNINITIALIZED:
188 case TRBinaryOpIC::SMI:
189 switch (result_type) {
190 case TRBinaryOpIC::UNINITIALIZED:
191 case TRBinaryOpIC::SMI:
192 return TypeInfo::Smi();
193 case TRBinaryOpIC::INT32:
194 return TypeInfo::Integer32();
195 case TRBinaryOpIC::HEAP_NUMBER:
196 return TypeInfo::Double();
197 default:
198 return unknown;
199 }
200 case TRBinaryOpIC::INT32:
201 if (expr->op() == Token::DIV ||
202 result_type == TRBinaryOpIC::HEAP_NUMBER) {
203 return TypeInfo::Double();
204 }
205 return TypeInfo::Integer32();
206 case TRBinaryOpIC::HEAP_NUMBER:
207 return TypeInfo::Double();
208 case TRBinaryOpIC::STRING:
209 case TRBinaryOpIC::GENERIC:
210 return unknown;
211 default:
212 return unknown;
213 }
214 }
215 return unknown;
216 }
217
218 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
219 Handle<Object> object = GetElement(map_, clause->position());
220 TypeInfo unknown = TypeInfo::Unknown();
221 if (!object->IsCode()) return unknown;
222 Handle<Code> code = Handle<Code>::cast(object);
223 if (!code->is_compare_ic_stub()) return unknown;
224
225 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
226 switch (state) {
227 case CompareIC::UNINITIALIZED:
228 case CompareIC::SMIS:
229 return TypeInfo::Smi();
230 case CompareIC::HEAP_NUMBERS:
231 return TypeInfo::Number();
232 case CompareIC::OBJECTS:
233 // TODO(kasperl): We really need a type for JS objects here.
234 return TypeInfo::NonPrimitive();
235 case CompareIC::GENERIC:
236 default:
237 return unknown;
238 }
239 }
240
241
242
243 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position,
244 Handle<String> name,
245 Code::Flags flags) {
246 Isolate* isolate = Isolate::Current();
247 Handle<Object> object = GetElement(map_, position);
248 if (object->IsUndefined()) return NULL;
249
250 if (*object == isolate->builtins()->builtin(Builtins::StoreIC_GlobalProxy)) {
251 // TODO(fschneider): We could collect the maps and signal that
252 // we need a generic store (or load) here.
253 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC);
254 return NULL;
255 } else if (object->IsMap()) {
256 ZoneMapList* types = new ZoneMapList(1);
257 types->Add(Handle<Map>::cast(object));
258 return types;
259 } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) {
260 ZoneMapList* types = new ZoneMapList(4);
261 ASSERT(object->IsCode());
262 isolate->stub_cache()->CollectMatchingMaps(types, *name, flags);
263 return types->length() > 0 ? types : NULL;
264 } else {
265 return NULL;
266 }
267 }
268
269
270 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) {
271 HandleScope scope;
272
273 const int kInitialCapacity = 16;
274 List<int> code_positions(kInitialCapacity);
275 List<int> source_positions(kInitialCapacity);
276 CollectPositions(*code, &code_positions, &source_positions);
277
278 int length = code_positions.length();
279 ASSERT(source_positions.length() == length);
280 for (int i = 0; i < length; i++) {
281 RelocInfo info(code->instruction_start() + code_positions[i],
282 RelocInfo::CODE_TARGET, 0);
283 Handle<Code> target(Code::GetCodeFromTargetAddress(info.target_address()));
284 int position = source_positions[i];
285 InlineCacheState state = target->ic_state();
286 Code::Kind kind = target->kind();
287 if (kind == Code::BINARY_OP_IC ||
288 kind == Code::TYPE_RECORDING_BINARY_OP_IC ||
289 kind == Code::COMPARE_IC) {
290 // TODO(kasperl): Avoid having multiple ICs with the same
291 // position by making sure that we have position information
292 // recorded for all binary ICs.
293 if (GetElement(map_, position)->IsUndefined()) {
294 SetElement(map_, position, target);
295 }
296 } else if (state == MONOMORPHIC) {
297 Map* map = target->FindFirstMap();
298 if (map == NULL) {
299 SetElement(map_, position, target);
300 } else {
301 SetElement(map_, position, Handle<Map>(map));
302 }
303 } else if (state == MEGAMORPHIC) {
304 SetElement(map_, position, target);
305 }
306 }
307 }
308
309
310 void TypeFeedbackOracle::CollectPositions(Code* code,
311 List<int>* code_positions,
312 List<int>* source_positions) {
313 AssertNoAllocation no_allocation;
314 int position = 0;
315 // Because the ICs we use for global variables access in the full
316 // code generator do not have any meaningful positions, we avoid
317 // collecting those by filtering out contextual code targets.
318 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
319 RelocInfo::kPositionMask;
320 for (RelocIterator it(code, mask); !it.done(); it.next()) {
321 RelocInfo* info = it.rinfo();
322 RelocInfo::Mode mode = info->rmode();
323 if (RelocInfo::IsCodeTarget(mode)) {
324 Code* target = Code::GetCodeFromTargetAddress(info->target_address());
325 if (target->is_inline_cache_stub()) {
326 InlineCacheState state = target->ic_state();
327 Code::Kind kind = target->kind();
328 if (kind == Code::BINARY_OP_IC) {
329 if (target->binary_op_type() == BinaryOpIC::GENERIC) continue;
330 } else if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) {
331 if (target->type_recording_binary_op_type() ==
332 TRBinaryOpIC::GENERIC) {
333 continue;
334 }
335 } else if (kind == Code::COMPARE_IC) {
336 if (target->compare_state() == CompareIC::GENERIC) continue;
337 } else {
338 if (kind == Code::CALL_IC && state == MONOMORPHIC &&
339 target->check_type() != RECEIVER_MAP_CHECK) continue;
340 if (state != MONOMORPHIC && state != MEGAMORPHIC) continue;
341 }
342 code_positions->Add(info->pc() - code->instruction_start());
343 source_positions->Add(position);
344 }
345 } else {
346 ASSERT(RelocInfo::IsPosition(mode));
347 position = info->data();
348 }
349 }
350 }
351
53 } } // namespace v8::internal 352 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/type-info.h ('k') | src/utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698