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

Side by Side Diff: src/code-stubs.cc

Issue 25494007: Reland "Hydrogenisation of binops" (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebase Created 7 years, 2 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/code-stubs.h ('k') | src/code-stubs-hydrogen.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 130
131 131
132 Handle<Code> CodeStub::GetCode(Isolate* isolate) { 132 Handle<Code> CodeStub::GetCode(Isolate* isolate) {
133 Factory* factory = isolate->factory(); 133 Factory* factory = isolate->factory();
134 Heap* heap = isolate->heap(); 134 Heap* heap = isolate->heap();
135 Code* code; 135 Code* code;
136 if (UseSpecialCache() 136 if (UseSpecialCache()
137 ? FindCodeInSpecialCache(&code, isolate) 137 ? FindCodeInSpecialCache(&code, isolate)
138 : FindCodeInCache(&code, isolate)) { 138 : FindCodeInCache(&code, isolate)) {
139 ASSERT(IsPregenerated(isolate) == code->is_pregenerated()); 139 ASSERT(IsPregenerated(isolate) == code->is_pregenerated());
140 ASSERT(GetCodeKind() == code->kind());
140 return Handle<Code>(code); 141 return Handle<Code>(code);
141 } 142 }
142 143
143 { 144 {
144 HandleScope scope(isolate); 145 HandleScope scope(isolate);
145 146
146 Handle<Code> new_object = GenerateCode(isolate); 147 Handle<Code> new_object = GenerateCode(isolate);
147 new_object->set_major_key(MajorKey()); 148 new_object->set_major_key(MajorKey());
148 FinishCode(new_object); 149 FinishCode(new_object);
149 RecordCodeGeneration(*new_object, isolate); 150 RecordCodeGeneration(*new_object, isolate);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 stream->Add("%s", MajorName(MajorKey(), false)); 197 stream->Add("%s", MajorName(MajorKey(), false));
197 } 198 }
198 199
199 200
200 void CodeStub::PrintName(StringStream* stream) { 201 void CodeStub::PrintName(StringStream* stream) {
201 PrintBaseName(stream); 202 PrintBaseName(stream);
202 PrintState(stream); 203 PrintState(stream);
203 } 204 }
204 205
205 206
206 void BinaryOpStub::Generate(MacroAssembler* masm) { 207 void BinaryOpStub::PrintBaseName(StringStream* stream) {
207 // Explicitly allow generation of nested stubs. It is safe here because 208 const char* op_name = Token::Name(op_);
208 // generation code does not use any raw pointers. 209 const char* ovr = "";
209 AllowStubCallsScope allow_stub_calls(masm, true); 210 if (mode_ == OVERWRITE_LEFT) ovr = "_ReuseLeft";
210 211 if (mode_ == OVERWRITE_RIGHT) ovr = "_ReuseRight";
211 BinaryOpIC::TypeInfo operands_type = Max(left_type_, right_type_); 212 stream->Add("BinaryOpStub_%s%s", op_name, ovr);
212 if (left_type_ == BinaryOpIC::ODDBALL && right_type_ == BinaryOpIC::ODDBALL) { 213 }
213 // The OddballStub handles a number and an oddball, not two oddballs. 214
214 operands_type = BinaryOpIC::GENERIC; 215
215 } 216 void BinaryOpStub::PrintState(StringStream* stream) {
216 switch (operands_type) { 217 stream->Add("(");
217 case BinaryOpIC::UNINITIALIZED: 218 stream->Add(StateToName(left_state_));
218 GenerateTypeTransition(masm); 219 stream->Add("*");
220 if (fixed_right_arg_.has_value) {
221 stream->Add("%d", fixed_right_arg_.value);
222 } else {
223 stream->Add(StateToName(right_state_));
224 }
225 stream->Add("->");
226 stream->Add(StateToName(result_state_));
227 stream->Add(")");
228 }
229
230
231 Maybe<Handle<Object> > BinaryOpStub::Result(Handle<Object> left,
232 Handle<Object> right,
233 Isolate* isolate) {
234 Handle<JSBuiltinsObject> builtins(isolate->js_builtins_object());
235 Builtins::JavaScript func = BinaryOpIC::TokenToJSBuiltin(op_);
236 Object* builtin = builtins->javascript_builtin(func);
237 Handle<JSFunction> builtin_function =
238 Handle<JSFunction>(JSFunction::cast(builtin), isolate);
239 bool caught_exception;
240 Handle<Object> result = Execution::Call(isolate, builtin_function, left,
241 1, &right, &caught_exception);
242 return Maybe<Handle<Object> >(!caught_exception, result);
243 }
244
245
246 void BinaryOpStub::Initialize() {
247 fixed_right_arg_.has_value = false;
248 left_state_ = right_state_ = result_state_ = NONE;
249 }
250
251
252 void BinaryOpStub::Generate(Token::Value op,
253 State left,
254 State right,
255 State result,
256 OverwriteMode mode,
257 Isolate* isolate) {
258 BinaryOpStub stub(INITIALIZED);
259 stub.op_ = op;
260 stub.left_state_ = left;
261 stub.right_state_ = right;
262 stub.result_state_ = result;
263 stub.mode_ = mode;
264 stub.GetCode(isolate);
265 }
266
267
268 void BinaryOpStub::Generate(Token::Value op,
269 State left,
270 int right,
271 State result,
272 OverwriteMode mode,
273 Isolate* isolate) {
274 BinaryOpStub stub(INITIALIZED);
275 stub.op_ = op;
276 stub.left_state_ = left;
277 stub.fixed_right_arg_.has_value = true;
278 stub.fixed_right_arg_.value = right;
279 stub.right_state_ = SMI;
280 stub.result_state_ = result;
281 stub.mode_ = mode;
282 stub.GetCode(isolate);
283 }
284
285
286 void BinaryOpStub::GenerateAheadOfTime(Isolate* isolate) {
287 Token::Value binop[] = {Token::SUB, Token::MOD, Token::DIV, Token::MUL,
288 Token::ADD, Token::SAR, Token::BIT_OR, Token::BIT_AND,
289 Token::BIT_XOR, Token::SHL, Token::SHR};
290 for (unsigned i = 0; i < ARRAY_SIZE(binop); i++) {
291 BinaryOpStub stub(UNINITIALIZED);
292 stub.op_ = binop[i];
293 stub.GetCode(isolate);
294 }
295
296 // TODO(olivf) We should investigate why adding stubs to the snapshot is so
297 // expensive at runtime. When solved we should be able to add most binops to
298 // the snapshot instead of hand-picking them.
299 // Generated list of commonly used stubs
300 Generate(Token::ADD, GENERIC, STRING, STRING, NO_OVERWRITE, isolate);
301 Generate(Token::ADD, GENERIC, STRING, STRING, OVERWRITE_RIGHT, isolate);
302 Generate(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE, isolate);
303 Generate(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
304 Generate(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE, isolate);
305 Generate(Token::ADD, INT32, INT32, NUMBER, OVERWRITE_LEFT, isolate);
306 Generate(Token::ADD, INT32, NUMBER, NUMBER, NO_OVERWRITE, isolate);
307 Generate(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
308 Generate(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
309 Generate(Token::ADD, INT32, SMI, INT32, NO_OVERWRITE, isolate);
310 Generate(Token::ADD, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
311 Generate(Token::ADD, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
312 Generate(Token::ADD, NUMBER, INT32, NUMBER, NO_OVERWRITE, isolate);
313 Generate(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_LEFT, isolate);
314 Generate(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT, isolate);
315 Generate(Token::ADD, NUMBER, NUMBER, NUMBER, NO_OVERWRITE, isolate);
316 Generate(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
317 Generate(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
318 Generate(Token::ADD, NUMBER, SMI, NUMBER, NO_OVERWRITE, isolate);
319 Generate(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
320 Generate(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT, isolate);
321 Generate(Token::ADD, SMI, INT32, INT32, NO_OVERWRITE, isolate);
322 Generate(Token::ADD, SMI, INT32, INT32, OVERWRITE_LEFT, isolate);
323 Generate(Token::ADD, SMI, INT32, NUMBER, NO_OVERWRITE, isolate);
324 Generate(Token::ADD, SMI, NUMBER, NUMBER, NO_OVERWRITE, isolate);
325 Generate(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
326 Generate(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
327 Generate(Token::ADD, SMI, SMI, INT32, OVERWRITE_LEFT, isolate);
328 Generate(Token::ADD, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
329 Generate(Token::ADD, STRING, GENERIC, STRING, NO_OVERWRITE, isolate);
330 Generate(Token::ADD, STRING, GENERIC, STRING, OVERWRITE_LEFT, isolate);
331 Generate(Token::ADD, STRING, GENERIC, STRING, OVERWRITE_RIGHT, isolate);
332 Generate(Token::ADD, STRING, STRING, STRING, NO_OVERWRITE, isolate);
333 Generate(Token::ADD, STRING, STRING, STRING, OVERWRITE_LEFT, isolate);
334 Generate(Token::ADD, STRING, STRING, STRING, OVERWRITE_RIGHT, isolate);
335 Generate(Token::BIT_AND, INT32, INT32, INT32, NO_OVERWRITE, isolate);
336 Generate(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
337 Generate(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_RIGHT, isolate);
338 Generate(Token::BIT_AND, INT32, INT32, SMI, NO_OVERWRITE, isolate);
339 Generate(Token::BIT_AND, INT32, INT32, SMI, OVERWRITE_RIGHT, isolate);
340 Generate(Token::BIT_AND, INT32, SMI, INT32, NO_OVERWRITE, isolate);
341 Generate(Token::BIT_AND, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
342 Generate(Token::BIT_AND, INT32, SMI, SMI, NO_OVERWRITE, isolate);
343 Generate(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_LEFT, isolate);
344 Generate(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
345 Generate(Token::BIT_AND, NUMBER, INT32, INT32, OVERWRITE_RIGHT, isolate);
346 Generate(Token::BIT_AND, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
347 Generate(Token::BIT_AND, NUMBER, SMI, SMI, OVERWRITE_RIGHT, isolate);
348 Generate(Token::BIT_AND, SMI, INT32, INT32, NO_OVERWRITE, isolate);
349 Generate(Token::BIT_AND, SMI, INT32, SMI, OVERWRITE_RIGHT, isolate);
350 Generate(Token::BIT_AND, SMI, NUMBER, SMI, OVERWRITE_RIGHT, isolate);
351 Generate(Token::BIT_AND, SMI, SMI, SMI, NO_OVERWRITE, isolate);
352 Generate(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
353 Generate(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
354 Generate(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
355 Generate(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_RIGHT, isolate);
356 Generate(Token::BIT_OR, INT32, INT32, SMI, OVERWRITE_LEFT, isolate);
357 Generate(Token::BIT_OR, INT32, SMI, INT32, NO_OVERWRITE, isolate);
358 Generate(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
359 Generate(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
360 Generate(Token::BIT_OR, INT32, SMI, SMI, NO_OVERWRITE, isolate);
361 Generate(Token::BIT_OR, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
362 Generate(Token::BIT_OR, NUMBER, SMI, INT32, NO_OVERWRITE, isolate);
363 Generate(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_LEFT, isolate);
364 Generate(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_RIGHT, isolate);
365 Generate(Token::BIT_OR, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
366 Generate(Token::BIT_OR, NUMBER, SMI, SMI, OVERWRITE_LEFT, isolate);
367 Generate(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_LEFT, isolate);
368 Generate(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_RIGHT, isolate);
369 Generate(Token::BIT_OR, SMI, INT32, SMI, OVERWRITE_RIGHT, isolate);
370 Generate(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
371 Generate(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
372 Generate(Token::BIT_XOR, INT32, INT32, INT32, NO_OVERWRITE, isolate);
373 Generate(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
374 Generate(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_RIGHT, isolate);
375 Generate(Token::BIT_XOR, INT32, INT32, SMI, NO_OVERWRITE, isolate);
376 Generate(Token::BIT_XOR, INT32, INT32, SMI, OVERWRITE_LEFT, isolate);
377 Generate(Token::BIT_XOR, INT32, NUMBER, SMI, NO_OVERWRITE, isolate);
378 Generate(Token::BIT_XOR, INT32, SMI, INT32, NO_OVERWRITE, isolate);
379 Generate(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
380 Generate(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
381 Generate(Token::BIT_XOR, NUMBER, INT32, INT32, NO_OVERWRITE, isolate);
382 Generate(Token::BIT_XOR, NUMBER, SMI, INT32, NO_OVERWRITE, isolate);
383 Generate(Token::BIT_XOR, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
384 Generate(Token::BIT_XOR, SMI, INT32, INT32, NO_OVERWRITE, isolate);
385 Generate(Token::BIT_XOR, SMI, INT32, INT32, OVERWRITE_LEFT, isolate);
386 Generate(Token::BIT_XOR, SMI, INT32, SMI, OVERWRITE_LEFT, isolate);
387 Generate(Token::BIT_XOR, SMI, SMI, SMI, NO_OVERWRITE, isolate);
388 Generate(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
389 Generate(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
390 Generate(Token::DIV, INT32, INT32, INT32, NO_OVERWRITE, isolate);
391 Generate(Token::DIV, INT32, INT32, NUMBER, NO_OVERWRITE, isolate);
392 Generate(Token::DIV, INT32, NUMBER, NUMBER, NO_OVERWRITE, isolate);
393 Generate(Token::DIV, INT32, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
394 Generate(Token::DIV, INT32, SMI, INT32, NO_OVERWRITE, isolate);
395 Generate(Token::DIV, INT32, SMI, NUMBER, NO_OVERWRITE, isolate);
396 Generate(Token::DIV, NUMBER, INT32, NUMBER, NO_OVERWRITE, isolate);
397 Generate(Token::DIV, NUMBER, INT32, NUMBER, OVERWRITE_LEFT, isolate);
398 Generate(Token::DIV, NUMBER, NUMBER, NUMBER, NO_OVERWRITE, isolate);
399 Generate(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
400 Generate(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
401 Generate(Token::DIV, NUMBER, SMI, NUMBER, NO_OVERWRITE, isolate);
402 Generate(Token::DIV, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
403 Generate(Token::DIV, SMI, INT32, INT32, NO_OVERWRITE, isolate);
404 Generate(Token::DIV, SMI, INT32, NUMBER, NO_OVERWRITE, isolate);
405 Generate(Token::DIV, SMI, INT32, NUMBER, OVERWRITE_LEFT, isolate);
406 Generate(Token::DIV, SMI, NUMBER, NUMBER, NO_OVERWRITE, isolate);
407 Generate(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
408 Generate(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
409 Generate(Token::DIV, SMI, SMI, NUMBER, NO_OVERWRITE, isolate);
410 Generate(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_LEFT, isolate);
411 Generate(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_RIGHT, isolate);
412 Generate(Token::DIV, SMI, SMI, SMI, NO_OVERWRITE, isolate);
413 Generate(Token::DIV, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
414 Generate(Token::DIV, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
415 Generate(Token::MOD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
416 Generate(Token::MOD, SMI, 16, SMI, OVERWRITE_LEFT, isolate);
417 Generate(Token::MOD, SMI, 2, SMI, NO_OVERWRITE, isolate);
418 Generate(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE, isolate);
419 Generate(Token::MOD, SMI, 32, SMI, NO_OVERWRITE, isolate);
420 Generate(Token::MOD, SMI, 4, SMI, NO_OVERWRITE, isolate);
421 Generate(Token::MOD, SMI, 4, SMI, OVERWRITE_LEFT, isolate);
422 Generate(Token::MOD, SMI, 8, SMI, NO_OVERWRITE, isolate);
423 Generate(Token::MOD, SMI, SMI, SMI, NO_OVERWRITE, isolate);
424 Generate(Token::MOD, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
425 Generate(Token::MUL, INT32, INT32, INT32, NO_OVERWRITE, isolate);
426 Generate(Token::MUL, INT32, INT32, NUMBER, NO_OVERWRITE, isolate);
427 Generate(Token::MUL, INT32, NUMBER, NUMBER, NO_OVERWRITE, isolate);
428 Generate(Token::MUL, INT32, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
429 Generate(Token::MUL, INT32, SMI, INT32, NO_OVERWRITE, isolate);
430 Generate(Token::MUL, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
431 Generate(Token::MUL, INT32, SMI, NUMBER, NO_OVERWRITE, isolate);
432 Generate(Token::MUL, NUMBER, INT32, NUMBER, NO_OVERWRITE, isolate);
433 Generate(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_LEFT, isolate);
434 Generate(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT, isolate);
435 Generate(Token::MUL, NUMBER, NUMBER, NUMBER, NO_OVERWRITE, isolate);
436 Generate(Token::MUL, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
437 Generate(Token::MUL, NUMBER, SMI, NUMBER, NO_OVERWRITE, isolate);
438 Generate(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
439 Generate(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT, isolate);
440 Generate(Token::MUL, SMI, INT32, INT32, NO_OVERWRITE, isolate);
441 Generate(Token::MUL, SMI, INT32, INT32, OVERWRITE_LEFT, isolate);
442 Generate(Token::MUL, SMI, INT32, NUMBER, NO_OVERWRITE, isolate);
443 Generate(Token::MUL, SMI, NUMBER, NUMBER, NO_OVERWRITE, isolate);
444 Generate(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
445 Generate(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
446 Generate(Token::MUL, SMI, SMI, INT32, NO_OVERWRITE, isolate);
447 Generate(Token::MUL, SMI, SMI, NUMBER, NO_OVERWRITE, isolate);
448 Generate(Token::MUL, SMI, SMI, NUMBER, OVERWRITE_LEFT, isolate);
449 Generate(Token::MUL, SMI, SMI, SMI, NO_OVERWRITE, isolate);
450 Generate(Token::MUL, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
451 Generate(Token::MUL, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
452 Generate(Token::SAR, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
453 Generate(Token::SAR, INT32, SMI, SMI, NO_OVERWRITE, isolate);
454 Generate(Token::SAR, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
455 Generate(Token::SAR, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
456 Generate(Token::SAR, NUMBER, SMI, SMI, OVERWRITE_RIGHT, isolate);
457 Generate(Token::SAR, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
458 Generate(Token::SAR, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
459 Generate(Token::SHL, INT32, SMI, INT32, NO_OVERWRITE, isolate);
460 Generate(Token::SHL, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
461 Generate(Token::SHL, INT32, SMI, SMI, NO_OVERWRITE, isolate);
462 Generate(Token::SHL, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
463 Generate(Token::SHL, NUMBER, SMI, SMI, OVERWRITE_RIGHT, isolate);
464 Generate(Token::SHL, SMI, SMI, INT32, NO_OVERWRITE, isolate);
465 Generate(Token::SHL, SMI, SMI, INT32, OVERWRITE_LEFT, isolate);
466 Generate(Token::SHL, SMI, SMI, INT32, OVERWRITE_RIGHT, isolate);
467 Generate(Token::SHL, SMI, SMI, SMI, NO_OVERWRITE, isolate);
468 Generate(Token::SHL, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
469 Generate(Token::SHL, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
470 Generate(Token::SHR, INT32, SMI, SMI, NO_OVERWRITE, isolate);
471 Generate(Token::SHR, INT32, SMI, SMI, OVERWRITE_LEFT, isolate);
472 Generate(Token::SHR, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
473 Generate(Token::SHR, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
474 Generate(Token::SHR, NUMBER, SMI, SMI, OVERWRITE_LEFT, isolate);
475 Generate(Token::SHR, SMI, SMI, SMI, NO_OVERWRITE, isolate);
476 Generate(Token::SHR, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
477 Generate(Token::SHR, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
478 Generate(Token::SUB, INT32, INT32, INT32, NO_OVERWRITE, isolate);
479 Generate(Token::SUB, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
480 Generate(Token::SUB, INT32, NUMBER, NUMBER, NO_OVERWRITE, isolate);
481 Generate(Token::SUB, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
482 Generate(Token::SUB, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
483 Generate(Token::SUB, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
484 Generate(Token::SUB, NUMBER, INT32, NUMBER, NO_OVERWRITE, isolate);
485 Generate(Token::SUB, NUMBER, INT32, NUMBER, OVERWRITE_LEFT, isolate);
486 Generate(Token::SUB, NUMBER, NUMBER, NUMBER, NO_OVERWRITE, isolate);
487 Generate(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
488 Generate(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
489 Generate(Token::SUB, NUMBER, SMI, NUMBER, NO_OVERWRITE, isolate);
490 Generate(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
491 Generate(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT, isolate);
492 Generate(Token::SUB, SMI, INT32, INT32, NO_OVERWRITE, isolate);
493 Generate(Token::SUB, SMI, NUMBER, NUMBER, NO_OVERWRITE, isolate);
494 Generate(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
495 Generate(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
496 Generate(Token::SUB, SMI, SMI, SMI, NO_OVERWRITE, isolate);
497 Generate(Token::SUB, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
498 Generate(Token::SUB, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
499 }
500
501
502 bool BinaryOpStub::can_encode_arg_value(int32_t value) const {
503 return op_ == Token::MOD && value > 0 && IsPowerOf2(value) &&
504 FixedRightArgValueBits::is_valid(WhichPowerOf2(value));
505 }
506
507
508 int BinaryOpStub::encode_arg_value(int32_t value) const {
509 ASSERT(can_encode_arg_value(value));
510 return WhichPowerOf2(value);
511 }
512
513
514 int32_t BinaryOpStub::decode_arg_value(int value) const {
515 return 1 << value;
516 }
517
518
519 int BinaryOpStub::encode_token(Token::Value op) const {
520 ASSERT(op >= FIRST_TOKEN && op <= LAST_TOKEN);
521 return op - FIRST_TOKEN;
522 }
523
524
525 Token::Value BinaryOpStub::decode_token(int op) const {
526 int res = op + FIRST_TOKEN;
527 ASSERT(res >= FIRST_TOKEN && res <= LAST_TOKEN);
528 return static_cast<Token::Value>(res);
529 }
530
531
532 const char* BinaryOpStub::StateToName(State state) {
533 switch (state) {
534 case NONE:
535 return "None";
536 case SMI:
537 return "Smi";
538 case INT32:
539 return "Int32";
540 case NUMBER:
541 return "Number";
542 case STRING:
543 return "String";
544 case GENERIC:
545 return "Generic";
546 }
547 return "";
548 }
549
550
551 void BinaryOpStub::UpdateStatus(Handle<Object> left,
552 Handle<Object> right,
553 Maybe<Handle<Object> > result) {
554 int old_state = GetExtraICState();
555
556 UpdateStatus(left, &left_state_);
557 UpdateStatus(right, &right_state_);
558
559 int32_t value;
560 bool new_has_fixed_right_arg =
561 right->ToInt32(&value) && can_encode_arg_value(value) &&
562 (left_state_ == SMI || left_state_ == INT32) &&
563 (result_state_ == NONE || !fixed_right_arg_.has_value);
564
565 fixed_right_arg_ = Maybe<int32_t>(new_has_fixed_right_arg, value);
566
567 if (result.has_value) UpdateStatus(result.value, &result_state_);
568
569 State max_input = Max(left_state_, right_state_);
570
571 // Avoid unnecessary Representation changes.
572 if (left_state_ == STRING && right_state_ < STRING) {
573 right_state_ = GENERIC;
574 } else if (right_state_ == STRING && left_state_ < STRING) {
575 left_state_ = GENERIC;
576 } else if ((right_state_ == GENERIC && left_state_ != STRING) ||
577 (left_state_ == GENERIC && right_state_ != STRING)) {
578 left_state_ = right_state_ = GENERIC;
579 } else if (!has_int_result() && op_ != Token::SHR &&
580 max_input <= NUMBER && max_input > result_state_) {
581 result_state_ = max_input;
582 }
583
584 ASSERT(result_state_ <= (has_int_result() ? INT32 : NUMBER) ||
585 op_ == Token::ADD);
586
587 if (old_state == GetExtraICState()) {
588 // Since the fpu is to precise, we might bail out on numbers which
589 // actually would truncate with 64 bit precision.
590 ASSERT(!CpuFeatures::IsSupported(SSE2) &&
591 result_state_ <= INT32);
592 result_state_ = NUMBER;
593 }
594 }
595
596
597 void BinaryOpStub::UpdateStatus(Handle<Object> object,
598 State* state) {
599 v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(object);
600 if (object->IsUndefined()) {
601 // Undefined will be automatically truncated for us by HChange.
602 type = (op_ == Token::BIT_AND || op_ == Token::BIT_OR ||
603 op_ == Token::BIT_XOR || op_ == Token::SAR ||
604 op_ == Token::SHL || op_ == Token::SHR)
605 ? TypeInfo::Integer32()
606 : TypeInfo::Double();
607 }
608 State int_state = SmiValuesAre32Bits() ? NUMBER : INT32;
609 State new_state = NONE;
610 if (type.IsSmi()) {
611 new_state = SMI;
612 } else if (type.IsInteger32()) {
613 new_state = int_state;
614 } else if (type.IsNumber()) {
615 new_state = NUMBER;
616 } else if (object->IsString() && operation() == Token::ADD) {
617 new_state = STRING;
618 } else {
619 new_state = GENERIC;
620 }
621 if ((new_state <= NUMBER && *state > NUMBER) ||
622 (new_state > NUMBER && *state <= NUMBER && *state != NONE)) {
623 new_state = GENERIC;
624 }
625 *state = Max(*state, new_state);
626 }
627
628
629 Handle<Type> BinaryOpStub::StateToType(State state,
630 Isolate* isolate) {
631 Handle<Type> t = handle(Type::None(), isolate);
632 switch (state) {
633 case NUMBER:
634 t = handle(Type::Union(t, handle(Type::Double(), isolate)), isolate);
635 // Fall through.
636 case INT32:
637 t = handle(Type::Union(t, handle(Type::Signed32(), isolate)), isolate);
638 // Fall through.
639 case SMI:
640 t = handle(Type::Union(t, handle(Type::Smi(), isolate)), isolate);
219 break; 641 break;
220 case BinaryOpIC::SMI: 642
221 GenerateSmiStub(masm); 643 case STRING:
644 t = handle(Type::Union(t, handle(Type::String(), isolate)), isolate);
222 break; 645 break;
223 case BinaryOpIC::INT32: 646 case GENERIC:
224 GenerateInt32Stub(masm); 647 return handle(Type::Any(), isolate);
225 break; 648 break;
226 case BinaryOpIC::NUMBER: 649 case NONE:
227 GenerateNumberStub(masm);
228 break; 650 break;
229 case BinaryOpIC::ODDBALL: 651 }
230 GenerateOddballStub(masm); 652 return t;
231 break; 653 }
232 case BinaryOpIC::STRING: 654
233 GenerateStringStub(masm); 655
234 break; 656 Handle<Type> BinaryOpStub::GetLeftType(Isolate* isolate) const {
235 case BinaryOpIC::GENERIC: 657 return StateToType(left_state_, isolate);
236 GenerateGeneric(masm); 658 }
237 break; 659
238 default: 660
239 UNREACHABLE(); 661 Handle<Type> BinaryOpStub::GetRightType(Isolate* isolate) const {
240 } 662 return StateToType(right_state_, isolate);
241 } 663 }
242 664
243 665
244 #define __ ACCESS_MASM(masm) 666 Handle<Type> BinaryOpStub::GetResultType(Isolate* isolate) const {
245 667 if (HasSideEffects(isolate)) return StateToType(NONE, isolate);
246 668 if (result_state_ == GENERIC && op_ == Token::ADD) {
247 void BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) { 669 return handle(Type::Union(handle(Type::Number(), isolate),
248 switch (op_) { 670 handle(Type::String(), isolate)), isolate);
249 case Token::ADD: 671 }
250 __ InvokeBuiltin(Builtins::ADD, CALL_FUNCTION); 672 ASSERT(result_state_ != GENERIC);
251 break; 673 if (result_state_ == NUMBER && op_ == Token::SHR) {
252 case Token::SUB: 674 return handle(Type::Unsigned32(), isolate);
253 __ InvokeBuiltin(Builtins::SUB, CALL_FUNCTION); 675 }
254 break; 676 return StateToType(result_state_, isolate);
255 case Token::MUL: 677 }
256 __ InvokeBuiltin(Builtins::MUL, CALL_FUNCTION); 678
257 break; 679
258 case Token::DIV:
259 __ InvokeBuiltin(Builtins::DIV, CALL_FUNCTION);
260 break;
261 case Token::MOD:
262 __ InvokeBuiltin(Builtins::MOD, CALL_FUNCTION);
263 break;
264 case Token::BIT_OR:
265 __ InvokeBuiltin(Builtins::BIT_OR, CALL_FUNCTION);
266 break;
267 case Token::BIT_AND:
268 __ InvokeBuiltin(Builtins::BIT_AND, CALL_FUNCTION);
269 break;
270 case Token::BIT_XOR:
271 __ InvokeBuiltin(Builtins::BIT_XOR, CALL_FUNCTION);
272 break;
273 case Token::SAR:
274 __ InvokeBuiltin(Builtins::SAR, CALL_FUNCTION);
275 break;
276 case Token::SHR:
277 __ InvokeBuiltin(Builtins::SHR, CALL_FUNCTION);
278 break;
279 case Token::SHL:
280 __ InvokeBuiltin(Builtins::SHL, CALL_FUNCTION);
281 break;
282 default:
283 UNREACHABLE();
284 }
285 }
286
287
288 #undef __
289
290
291 void BinaryOpStub::PrintName(StringStream* stream) {
292 const char* op_name = Token::Name(op_);
293 const char* overwrite_name;
294 switch (mode_) {
295 case NO_OVERWRITE: overwrite_name = "Alloc"; break;
296 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
297 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
298 default: overwrite_name = "UnknownOverwrite"; break;
299 }
300 stream->Add("BinaryOpStub_%s_%s_%s+%s",
301 op_name,
302 overwrite_name,
303 BinaryOpIC::GetName(left_type_),
304 BinaryOpIC::GetName(right_type_));
305 }
306
307
308 void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
309 ASSERT(left_type_ == BinaryOpIC::STRING || right_type_ == BinaryOpIC::STRING);
310 ASSERT(op_ == Token::ADD);
311 if (left_type_ == BinaryOpIC::STRING && right_type_ == BinaryOpIC::STRING) {
312 GenerateBothStringStub(masm);
313 return;
314 }
315 // Try to add arguments as strings, otherwise, transition to the generic
316 // BinaryOpIC type.
317 GenerateAddStrings(masm);
318 GenerateTypeTransition(masm);
319 }
320
321
322 InlineCacheState ICCompareStub::GetICState() { 680 InlineCacheState ICCompareStub::GetICState() {
323 CompareIC::State state = Max(left_, right_); 681 CompareIC::State state = Max(left_, right_);
324 switch (state) { 682 switch (state) {
325 case CompareIC::UNINITIALIZED: 683 case CompareIC::UNINITIALIZED:
326 return ::v8::internal::UNINITIALIZED; 684 return ::v8::internal::UNINITIALIZED;
327 case CompareIC::SMI: 685 case CompareIC::SMI:
328 case CompareIC::NUMBER: 686 case CompareIC::NUMBER:
329 case CompareIC::INTERNALIZED_STRING: 687 case CompareIC::INTERNALIZED_STRING:
330 case CompareIC::STRING: 688 case CompareIC::STRING:
331 case CompareIC::UNIQUE_NAME: 689 case CompareIC::UNIQUE_NAME:
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 InstallDescriptor(isolate, &stub3); 1153 InstallDescriptor(isolate, &stub3);
796 } 1154 }
797 1155
798 InternalArrayConstructorStub::InternalArrayConstructorStub( 1156 InternalArrayConstructorStub::InternalArrayConstructorStub(
799 Isolate* isolate) { 1157 Isolate* isolate) {
800 InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 1158 InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
801 } 1159 }
802 1160
803 1161
804 } } // namespace v8::internal 1162 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/code-stubs.h ('k') | src/code-stubs-hydrogen.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698