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

Side by Side Diff: src/x64/full-codegen-x64.cc

Issue 8386037: Remove the forward-bailout stack from the non-optimizing compiler. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 1 month 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/mips/full-codegen-mips.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 360 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 371
372 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { 372 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
373 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 373 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
374 MemOperand operand = codegen()->VarOperand(var, result_register()); 374 MemOperand operand = codegen()->VarOperand(var, result_register());
375 __ push(operand); 375 __ push(operand);
376 } 376 }
377 377
378 378
379 void FullCodeGenerator::TestContext::Plug(Variable* var) const { 379 void FullCodeGenerator::TestContext::Plug(Variable* var) const {
380 codegen()->GetVar(result_register(), var); 380 codegen()->GetVar(result_register(), var);
381 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 381 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
382 codegen()->DoTest(this); 382 codegen()->DoTest(this);
383 } 383 }
384 384
385 385
386 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 386 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
387 } 387 }
388 388
389 389
390 void FullCodeGenerator::AccumulatorValueContext::Plug( 390 void FullCodeGenerator::AccumulatorValueContext::Plug(
391 Heap::RootListIndex index) const { 391 Heap::RootListIndex index) const {
392 __ LoadRoot(result_register(), index); 392 __ LoadRoot(result_register(), index);
393 } 393 }
394 394
395 395
396 void FullCodeGenerator::StackValueContext::Plug( 396 void FullCodeGenerator::StackValueContext::Plug(
397 Heap::RootListIndex index) const { 397 Heap::RootListIndex index) const {
398 __ PushRoot(index); 398 __ PushRoot(index);
399 } 399 }
400 400
401 401
402 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 402 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
403 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, 403 codegen()->PrepareForBailoutBeforeSplit(condition(),
404 true, 404 true,
405 true_label_, 405 true_label_,
406 false_label_); 406 false_label_);
407 if (index == Heap::kUndefinedValueRootIndex || 407 if (index == Heap::kUndefinedValueRootIndex ||
408 index == Heap::kNullValueRootIndex || 408 index == Heap::kNullValueRootIndex ||
409 index == Heap::kFalseValueRootIndex) { 409 index == Heap::kFalseValueRootIndex) {
410 if (false_label_ != fall_through_) __ jmp(false_label_); 410 if (false_label_ != fall_through_) __ jmp(false_label_);
411 } else if (index == Heap::kTrueValueRootIndex) { 411 } else if (index == Heap::kTrueValueRootIndex) {
412 if (true_label_ != fall_through_) __ jmp(true_label_); 412 if (true_label_ != fall_through_) __ jmp(true_label_);
413 } else { 413 } else {
(...skipping 12 matching lines...) Expand all
426 __ Move(result_register(), lit); 426 __ Move(result_register(), lit);
427 } 427 }
428 428
429 429
430 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 430 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
431 __ Push(lit); 431 __ Push(lit);
432 } 432 }
433 433
434 434
435 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 435 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
436 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, 436 codegen()->PrepareForBailoutBeforeSplit(condition(),
437 true, 437 true,
438 true_label_, 438 true_label_,
439 false_label_); 439 false_label_);
440 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. 440 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals.
441 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 441 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
442 if (false_label_ != fall_through_) __ jmp(false_label_); 442 if (false_label_ != fall_through_) __ jmp(false_label_);
443 } else if (lit->IsTrue() || lit->IsJSObject()) { 443 } else if (lit->IsTrue() || lit->IsJSObject()) {
444 if (true_label_ != fall_through_) __ jmp(true_label_); 444 if (true_label_ != fall_through_) __ jmp(true_label_);
445 } else if (lit->IsString()) { 445 } else if (lit->IsString()) {
446 if (String::cast(*lit)->length() == 0) { 446 if (String::cast(*lit)->length() == 0) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 __ movq(Operand(rsp, 0), reg); 485 __ movq(Operand(rsp, 0), reg);
486 } 486 }
487 487
488 488
489 void FullCodeGenerator::TestContext::DropAndPlug(int count, 489 void FullCodeGenerator::TestContext::DropAndPlug(int count,
490 Register reg) const { 490 Register reg) const {
491 ASSERT(count > 0); 491 ASSERT(count > 0);
492 // For simplicity we always test the accumulator register. 492 // For simplicity we always test the accumulator register.
493 __ Drop(count); 493 __ Drop(count);
494 __ Move(result_register(), reg); 494 __ Move(result_register(), reg);
495 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 495 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
496 codegen()->DoTest(this); 496 codegen()->DoTest(this);
497 } 497 }
498 498
499 499
500 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 500 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
501 Label* materialize_false) const { 501 Label* materialize_false) const {
502 ASSERT(materialize_true == materialize_false); 502 ASSERT(materialize_true == materialize_false);
503 __ bind(materialize_true); 503 __ bind(materialize_true);
504 } 504 }
505 505
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 549
550 550
551 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { 551 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
552 Heap::RootListIndex value_root_index = 552 Heap::RootListIndex value_root_index =
553 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 553 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
554 __ PushRoot(value_root_index); 554 __ PushRoot(value_root_index);
555 } 555 }
556 556
557 557
558 void FullCodeGenerator::TestContext::Plug(bool flag) const { 558 void FullCodeGenerator::TestContext::Plug(bool flag) const {
559 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, 559 codegen()->PrepareForBailoutBeforeSplit(condition(),
560 true, 560 true,
561 true_label_, 561 true_label_,
562 false_label_); 562 false_label_);
563 if (flag) { 563 if (flag) {
564 if (true_label_ != fall_through_) __ jmp(true_label_); 564 if (true_label_ != fall_through_) __ jmp(true_label_);
565 } else { 565 } else {
566 if (false_label_ != fall_through_) __ jmp(false_label_); 566 if (false_label_ != fall_through_) __ jmp(false_label_);
567 } 567 }
568 } 568 }
569 569
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 __ movq(location, src); 641 __ movq(location, src);
642 642
643 // Emit the write barrier code if the location is in the heap. 643 // Emit the write barrier code if the location is in the heap.
644 if (var->IsContextSlot()) { 644 if (var->IsContextSlot()) {
645 int offset = Context::SlotOffset(var->index()); 645 int offset = Context::SlotOffset(var->index());
646 __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs); 646 __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
647 } 647 }
648 } 648 }
649 649
650 650
651 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, 651 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
652 bool should_normalize, 652 bool should_normalize,
653 Label* if_true, 653 Label* if_true,
654 Label* if_false) { 654 Label* if_false) {
655 // Only prepare for bailouts before splits if we're in a test 655 // Only prepare for bailouts before splits if we're in a test
656 // context. Otherwise, we let the Visit function deal with the 656 // context. Otherwise, we let the Visit function deal with the
657 // preparation to avoid preparing with the same AST id twice. 657 // preparation to avoid preparing with the same AST id twice.
658 if (!context()->IsTest() || !info_->IsOptimizable()) return; 658 if (!context()->IsTest() || !info_->IsOptimizable()) return;
659 659
660 Label skip; 660 Label skip;
661 if (should_normalize) __ jmp(&skip, Label::kNear); 661 if (should_normalize) __ jmp(&skip, Label::kNear);
662 662 PrepareForBailout(expr, TOS_REG);
663 ForwardBailoutStack* current = forward_bailout_stack_;
664 while (current != NULL) {
665 PrepareForBailout(current->expr(), state);
666 current = current->parent();
667 }
668
669 if (should_normalize) { 663 if (should_normalize) {
670 __ CompareRoot(rax, Heap::kTrueValueRootIndex); 664 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
671 Split(equal, if_true, if_false, NULL); 665 Split(equal, if_true, if_false, NULL);
672 __ bind(&skip); 666 __ bind(&skip);
673 } 667 }
674 } 668 }
675 669
676 670
677 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, 671 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
678 VariableMode mode, 672 VariableMode mode,
(...skipping 1578 matching lines...) Expand 10 before | Expand all | Expand 10 after
2257 __ Set(rax, arg_count); 2251 __ Set(rax, arg_count);
2258 __ movq(rdi, Operand(rsp, arg_count * kPointerSize)); 2252 __ movq(rdi, Operand(rsp, arg_count * kPointerSize));
2259 2253
2260 Handle<Code> construct_builtin = 2254 Handle<Code> construct_builtin =
2261 isolate()->builtins()->JSConstructCall(); 2255 isolate()->builtins()->JSConstructCall();
2262 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 2256 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
2263 context()->Plug(rax); 2257 context()->Plug(rax);
2264 } 2258 }
2265 2259
2266 2260
2267 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { 2261 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2262 ZoneList<Expression*>* args = expr->arguments();
2268 ASSERT(args->length() == 1); 2263 ASSERT(args->length() == 1);
2269 2264
2270 VisitForAccumulatorValue(args->at(0)); 2265 VisitForAccumulatorValue(args->at(0));
2271 2266
2272 Label materialize_true, materialize_false; 2267 Label materialize_true, materialize_false;
2273 Label* if_true = NULL; 2268 Label* if_true = NULL;
2274 Label* if_false = NULL; 2269 Label* if_false = NULL;
2275 Label* fall_through = NULL; 2270 Label* fall_through = NULL;
2276 context()->PrepareTest(&materialize_true, &materialize_false, 2271 context()->PrepareTest(&materialize_true, &materialize_false,
2277 &if_true, &if_false, &fall_through); 2272 &if_true, &if_false, &fall_through);
2278 2273
2279 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2274 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2280 __ JumpIfSmi(rax, if_true); 2275 __ JumpIfSmi(rax, if_true);
2281 __ jmp(if_false); 2276 __ jmp(if_false);
2282 2277
2283 context()->Plug(if_true, if_false); 2278 context()->Plug(if_true, if_false);
2284 } 2279 }
2285 2280
2286 2281
2287 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 2282 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
2283 ZoneList<Expression*>* args = expr->arguments();
2288 ASSERT(args->length() == 1); 2284 ASSERT(args->length() == 1);
2289 2285
2290 VisitForAccumulatorValue(args->at(0)); 2286 VisitForAccumulatorValue(args->at(0));
2291 2287
2292 Label materialize_true, materialize_false; 2288 Label materialize_true, materialize_false;
2293 Label* if_true = NULL; 2289 Label* if_true = NULL;
2294 Label* if_false = NULL; 2290 Label* if_false = NULL;
2295 Label* fall_through = NULL; 2291 Label* fall_through = NULL;
2296 context()->PrepareTest(&materialize_true, &materialize_false, 2292 context()->PrepareTest(&materialize_true, &materialize_false,
2297 &if_true, &if_false, &fall_through); 2293 &if_true, &if_false, &fall_through);
2298 2294
2299 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2295 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2300 Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax); 2296 Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
2301 Split(non_negative_smi, if_true, if_false, fall_through); 2297 Split(non_negative_smi, if_true, if_false, fall_through);
2302 2298
2303 context()->Plug(if_true, if_false); 2299 context()->Plug(if_true, if_false);
2304 } 2300 }
2305 2301
2306 2302
2307 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 2303 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
2304 ZoneList<Expression*>* args = expr->arguments();
2308 ASSERT(args->length() == 1); 2305 ASSERT(args->length() == 1);
2309 2306
2310 VisitForAccumulatorValue(args->at(0)); 2307 VisitForAccumulatorValue(args->at(0));
2311 2308
2312 Label materialize_true, materialize_false; 2309 Label materialize_true, materialize_false;
2313 Label* if_true = NULL; 2310 Label* if_true = NULL;
2314 Label* if_false = NULL; 2311 Label* if_false = NULL;
2315 Label* fall_through = NULL; 2312 Label* fall_through = NULL;
2316 context()->PrepareTest(&materialize_true, &materialize_false, 2313 context()->PrepareTest(&materialize_true, &materialize_false,
2317 &if_true, &if_false, &fall_through); 2314 &if_true, &if_false, &fall_through);
2318 2315
2319 __ JumpIfSmi(rax, if_false); 2316 __ JumpIfSmi(rax, if_false);
2320 __ CompareRoot(rax, Heap::kNullValueRootIndex); 2317 __ CompareRoot(rax, Heap::kNullValueRootIndex);
2321 __ j(equal, if_true); 2318 __ j(equal, if_true);
2322 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2319 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2323 // Undetectable objects behave like undefined when tested with typeof. 2320 // Undetectable objects behave like undefined when tested with typeof.
2324 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2321 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2325 Immediate(1 << Map::kIsUndetectable)); 2322 Immediate(1 << Map::kIsUndetectable));
2326 __ j(not_zero, if_false); 2323 __ j(not_zero, if_false);
2327 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 2324 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2328 __ cmpq(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2325 __ cmpq(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2329 __ j(below, if_false); 2326 __ j(below, if_false);
2330 __ cmpq(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2327 __ cmpq(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
2331 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2328 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2332 Split(below_equal, if_true, if_false, fall_through); 2329 Split(below_equal, if_true, if_false, fall_through);
2333 2330
2334 context()->Plug(if_true, if_false); 2331 context()->Plug(if_true, if_false);
2335 } 2332 }
2336 2333
2337 2334
2338 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 2335 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
2336 ZoneList<Expression*>* args = expr->arguments();
2339 ASSERT(args->length() == 1); 2337 ASSERT(args->length() == 1);
2340 2338
2341 VisitForAccumulatorValue(args->at(0)); 2339 VisitForAccumulatorValue(args->at(0));
2342 2340
2343 Label materialize_true, materialize_false; 2341 Label materialize_true, materialize_false;
2344 Label* if_true = NULL; 2342 Label* if_true = NULL;
2345 Label* if_false = NULL; 2343 Label* if_false = NULL;
2346 Label* fall_through = NULL; 2344 Label* fall_through = NULL;
2347 context()->PrepareTest(&materialize_true, &materialize_false, 2345 context()->PrepareTest(&materialize_true, &materialize_false,
2348 &if_true, &if_false, &fall_through); 2346 &if_true, &if_false, &fall_through);
2349 2347
2350 __ JumpIfSmi(rax, if_false); 2348 __ JumpIfSmi(rax, if_false);
2351 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx); 2349 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx);
2352 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2350 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2353 Split(above_equal, if_true, if_false, fall_through); 2351 Split(above_equal, if_true, if_false, fall_through);
2354 2352
2355 context()->Plug(if_true, if_false); 2353 context()->Plug(if_true, if_false);
2356 } 2354 }
2357 2355
2358 2356
2359 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2357 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
2358 ZoneList<Expression*>* args = expr->arguments();
2360 ASSERT(args->length() == 1); 2359 ASSERT(args->length() == 1);
2361 2360
2362 VisitForAccumulatorValue(args->at(0)); 2361 VisitForAccumulatorValue(args->at(0));
2363 2362
2364 Label materialize_true, materialize_false; 2363 Label materialize_true, materialize_false;
2365 Label* if_true = NULL; 2364 Label* if_true = NULL;
2366 Label* if_false = NULL; 2365 Label* if_false = NULL;
2367 Label* fall_through = NULL; 2366 Label* fall_through = NULL;
2368 context()->PrepareTest(&materialize_true, &materialize_false, 2367 context()->PrepareTest(&materialize_true, &materialize_false,
2369 &if_true, &if_false, &fall_through); 2368 &if_true, &if_false, &fall_through);
2370 2369
2371 __ JumpIfSmi(rax, if_false); 2370 __ JumpIfSmi(rax, if_false);
2372 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2371 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2373 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2372 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2374 Immediate(1 << Map::kIsUndetectable)); 2373 Immediate(1 << Map::kIsUndetectable));
2375 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2374 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2376 Split(not_zero, if_true, if_false, fall_through); 2375 Split(not_zero, if_true, if_false, fall_through);
2377 2376
2378 context()->Plug(if_true, if_false); 2377 context()->Plug(if_true, if_false);
2379 } 2378 }
2380 2379
2381 2380
2382 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2381 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2383 ZoneList<Expression*>* args) { 2382 CallRuntime* expr) {
2383 ZoneList<Expression*>* args = expr->arguments();
2384 ASSERT(args->length() == 1); 2384 ASSERT(args->length() == 1);
2385 2385
2386 VisitForAccumulatorValue(args->at(0)); 2386 VisitForAccumulatorValue(args->at(0));
2387 2387
2388 Label materialize_true, materialize_false; 2388 Label materialize_true, materialize_false;
2389 Label* if_true = NULL; 2389 Label* if_true = NULL;
2390 Label* if_false = NULL; 2390 Label* if_false = NULL;
2391 Label* fall_through = NULL; 2391 Label* fall_through = NULL;
2392 context()->PrepareTest(&materialize_true, &materialize_false, 2392 context()->PrepareTest(&materialize_true, &materialize_false,
2393 &if_true, &if_false, &fall_through); 2393 &if_true, &if_false, &fall_through);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2449 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalContextOffset)); 2449 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalContextOffset));
2450 __ cmpq(rcx, 2450 __ cmpq(rcx,
2451 ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); 2451 ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
2452 __ j(not_equal, if_false); 2452 __ j(not_equal, if_false);
2453 // Set the bit in the map to indicate that it has been checked safe for 2453 // Set the bit in the map to indicate that it has been checked safe for
2454 // default valueOf and set true result. 2454 // default valueOf and set true result.
2455 __ or_(FieldOperand(rbx, Map::kBitField2Offset), 2455 __ or_(FieldOperand(rbx, Map::kBitField2Offset),
2456 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); 2456 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
2457 __ jmp(if_true); 2457 __ jmp(if_true);
2458 2458
2459 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2459 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2460 context()->Plug(if_true, if_false); 2460 context()->Plug(if_true, if_false);
2461 } 2461 }
2462 2462
2463 2463
2464 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2464 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
2465 ZoneList<Expression*>* args = expr->arguments();
2465 ASSERT(args->length() == 1); 2466 ASSERT(args->length() == 1);
2466 2467
2467 VisitForAccumulatorValue(args->at(0)); 2468 VisitForAccumulatorValue(args->at(0));
2468 2469
2469 Label materialize_true, materialize_false; 2470 Label materialize_true, materialize_false;
2470 Label* if_true = NULL; 2471 Label* if_true = NULL;
2471 Label* if_false = NULL; 2472 Label* if_false = NULL;
2472 Label* fall_through = NULL; 2473 Label* fall_through = NULL;
2473 context()->PrepareTest(&materialize_true, &materialize_false, 2474 context()->PrepareTest(&materialize_true, &materialize_false,
2474 &if_true, &if_false, &fall_through); 2475 &if_true, &if_false, &fall_through);
2475 2476
2476 __ JumpIfSmi(rax, if_false); 2477 __ JumpIfSmi(rax, if_false);
2477 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 2478 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2478 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2479 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2479 Split(equal, if_true, if_false, fall_through); 2480 Split(equal, if_true, if_false, fall_through);
2480 2481
2481 context()->Plug(if_true, if_false); 2482 context()->Plug(if_true, if_false);
2482 } 2483 }
2483 2484
2484 2485
2485 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2486 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
2487 ZoneList<Expression*>* args = expr->arguments();
2486 ASSERT(args->length() == 1); 2488 ASSERT(args->length() == 1);
2487 2489
2488 VisitForAccumulatorValue(args->at(0)); 2490 VisitForAccumulatorValue(args->at(0));
2489 2491
2490 Label materialize_true, materialize_false; 2492 Label materialize_true, materialize_false;
2491 Label* if_true = NULL; 2493 Label* if_true = NULL;
2492 Label* if_false = NULL; 2494 Label* if_false = NULL;
2493 Label* fall_through = NULL; 2495 Label* fall_through = NULL;
2494 context()->PrepareTest(&materialize_true, &materialize_false, 2496 context()->PrepareTest(&materialize_true, &materialize_false,
2495 &if_true, &if_false, &fall_through); 2497 &if_true, &if_false, &fall_through);
2496 2498
2497 __ JumpIfSmi(rax, if_false); 2499 __ JumpIfSmi(rax, if_false);
2498 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); 2500 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
2499 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2501 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2500 Split(equal, if_true, if_false, fall_through); 2502 Split(equal, if_true, if_false, fall_through);
2501 2503
2502 context()->Plug(if_true, if_false); 2504 context()->Plug(if_true, if_false);
2503 } 2505 }
2504 2506
2505 2507
2506 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2508 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
2509 ZoneList<Expression*>* args = expr->arguments();
2507 ASSERT(args->length() == 1); 2510 ASSERT(args->length() == 1);
2508 2511
2509 VisitForAccumulatorValue(args->at(0)); 2512 VisitForAccumulatorValue(args->at(0));
2510 2513
2511 Label materialize_true, materialize_false; 2514 Label materialize_true, materialize_false;
2512 Label* if_true = NULL; 2515 Label* if_true = NULL;
2513 Label* if_false = NULL; 2516 Label* if_false = NULL;
2514 Label* fall_through = NULL; 2517 Label* fall_through = NULL;
2515 context()->PrepareTest(&materialize_true, &materialize_false, 2518 context()->PrepareTest(&materialize_true, &materialize_false,
2516 &if_true, &if_false, &fall_through); 2519 &if_true, &if_false, &fall_through);
2517 2520
2518 __ JumpIfSmi(rax, if_false); 2521 __ JumpIfSmi(rax, if_false);
2519 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); 2522 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
2520 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2523 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2521 Split(equal, if_true, if_false, fall_through); 2524 Split(equal, if_true, if_false, fall_through);
2522 2525
2523 context()->Plug(if_true, if_false); 2526 context()->Plug(if_true, if_false);
2524 } 2527 }
2525 2528
2526 2529
2527 2530
2528 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2531 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
2529 ASSERT(args->length() == 0); 2532 ASSERT(expr->arguments()->length() == 0);
2530 2533
2531 Label materialize_true, materialize_false; 2534 Label materialize_true, materialize_false;
2532 Label* if_true = NULL; 2535 Label* if_true = NULL;
2533 Label* if_false = NULL; 2536 Label* if_false = NULL;
2534 Label* fall_through = NULL; 2537 Label* fall_through = NULL;
2535 context()->PrepareTest(&materialize_true, &materialize_false, 2538 context()->PrepareTest(&materialize_true, &materialize_false,
2536 &if_true, &if_false, &fall_through); 2539 &if_true, &if_false, &fall_through);
2537 2540
2538 // Get the frame pointer for the calling frame. 2541 // Get the frame pointer for the calling frame.
2539 __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2542 __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2540 2543
2541 // Skip the arguments adaptor frame if it exists. 2544 // Skip the arguments adaptor frame if it exists.
2542 Label check_frame_marker; 2545 Label check_frame_marker;
2543 __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset), 2546 __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset),
2544 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2547 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2545 __ j(not_equal, &check_frame_marker); 2548 __ j(not_equal, &check_frame_marker);
2546 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 2549 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
2547 2550
2548 // Check the marker in the calling frame. 2551 // Check the marker in the calling frame.
2549 __ bind(&check_frame_marker); 2552 __ bind(&check_frame_marker);
2550 __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset), 2553 __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
2551 Smi::FromInt(StackFrame::CONSTRUCT)); 2554 Smi::FromInt(StackFrame::CONSTRUCT));
2552 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2555 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2553 Split(equal, if_true, if_false, fall_through); 2556 Split(equal, if_true, if_false, fall_through);
2554 2557
2555 context()->Plug(if_true, if_false); 2558 context()->Plug(if_true, if_false);
2556 } 2559 }
2557 2560
2558 2561
2559 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2562 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
2563 ZoneList<Expression*>* args = expr->arguments();
2560 ASSERT(args->length() == 2); 2564 ASSERT(args->length() == 2);
2561 2565
2562 // Load the two objects into registers and perform the comparison. 2566 // Load the two objects into registers and perform the comparison.
2563 VisitForStackValue(args->at(0)); 2567 VisitForStackValue(args->at(0));
2564 VisitForAccumulatorValue(args->at(1)); 2568 VisitForAccumulatorValue(args->at(1));
2565 2569
2566 Label materialize_true, materialize_false; 2570 Label materialize_true, materialize_false;
2567 Label* if_true = NULL; 2571 Label* if_true = NULL;
2568 Label* if_false = NULL; 2572 Label* if_false = NULL;
2569 Label* fall_through = NULL; 2573 Label* fall_through = NULL;
2570 context()->PrepareTest(&materialize_true, &materialize_false, 2574 context()->PrepareTest(&materialize_true, &materialize_false,
2571 &if_true, &if_false, &fall_through); 2575 &if_true, &if_false, &fall_through);
2572 2576
2573 __ pop(rbx); 2577 __ pop(rbx);
2574 __ cmpq(rax, rbx); 2578 __ cmpq(rax, rbx);
2575 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2579 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2576 Split(equal, if_true, if_false, fall_through); 2580 Split(equal, if_true, if_false, fall_through);
2577 2581
2578 context()->Plug(if_true, if_false); 2582 context()->Plug(if_true, if_false);
2579 } 2583 }
2580 2584
2581 2585
2582 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2586 void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
2587 ZoneList<Expression*>* args = expr->arguments();
2583 ASSERT(args->length() == 1); 2588 ASSERT(args->length() == 1);
2584 2589
2585 // ArgumentsAccessStub expects the key in rdx and the formal 2590 // ArgumentsAccessStub expects the key in rdx and the formal
2586 // parameter count in rax. 2591 // parameter count in rax.
2587 VisitForAccumulatorValue(args->at(0)); 2592 VisitForAccumulatorValue(args->at(0));
2588 __ movq(rdx, rax); 2593 __ movq(rdx, rax);
2589 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters())); 2594 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
2590 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2595 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2591 __ CallStub(&stub); 2596 __ CallStub(&stub);
2592 context()->Plug(rax); 2597 context()->Plug(rax);
2593 } 2598 }
2594 2599
2595 2600
2596 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2601 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
2597 ASSERT(args->length() == 0); 2602 ASSERT(expr->arguments()->length() == 0);
2598 2603
2599 Label exit; 2604 Label exit;
2600 // Get the number of formal parameters. 2605 // Get the number of formal parameters.
2601 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters())); 2606 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
2602 2607
2603 // Check if the calling frame is an arguments adaptor frame. 2608 // Check if the calling frame is an arguments adaptor frame.
2604 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2609 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2605 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), 2610 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
2606 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2611 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2607 __ j(not_equal, &exit, Label::kNear); 2612 __ j(not_equal, &exit, Label::kNear);
2608 2613
2609 // Arguments adaptor case: Read the arguments length from the 2614 // Arguments adaptor case: Read the arguments length from the
2610 // adaptor frame. 2615 // adaptor frame.
2611 __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2616 __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2612 2617
2613 __ bind(&exit); 2618 __ bind(&exit);
2614 if (FLAG_debug_code) __ AbortIfNotSmi(rax); 2619 if (FLAG_debug_code) __ AbortIfNotSmi(rax);
2615 context()->Plug(rax); 2620 context()->Plug(rax);
2616 } 2621 }
2617 2622
2618 2623
2619 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2624 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
2625 ZoneList<Expression*>* args = expr->arguments();
2620 ASSERT(args->length() == 1); 2626 ASSERT(args->length() == 1);
2621 Label done, null, function, non_function_constructor; 2627 Label done, null, function, non_function_constructor;
2622 2628
2623 VisitForAccumulatorValue(args->at(0)); 2629 VisitForAccumulatorValue(args->at(0));
2624 2630
2625 // If the object is a smi, we return null. 2631 // If the object is a smi, we return null.
2626 __ JumpIfSmi(rax, &null); 2632 __ JumpIfSmi(rax, &null);
2627 2633
2628 // Check that the object is a JS object but take special care of JS 2634 // Check that the object is a JS object but take special care of JS
2629 // functions to make sure they have 'Function' as their class. 2635 // functions to make sure they have 'Function' as their class.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2669 __ bind(&null); 2675 __ bind(&null);
2670 __ LoadRoot(rax, Heap::kNullValueRootIndex); 2676 __ LoadRoot(rax, Heap::kNullValueRootIndex);
2671 2677
2672 // All done. 2678 // All done.
2673 __ bind(&done); 2679 __ bind(&done);
2674 2680
2675 context()->Plug(rax); 2681 context()->Plug(rax);
2676 } 2682 }
2677 2683
2678 2684
2679 void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { 2685 void FullCodeGenerator::EmitLog(CallRuntime* expr) {
2680 // Conditionally generate a log call. 2686 // Conditionally generate a log call.
2681 // Args: 2687 // Args:
2682 // 0 (literal string): The type of logging (corresponds to the flags). 2688 // 0 (literal string): The type of logging (corresponds to the flags).
2683 // This is used to determine whether or not to generate the log call. 2689 // This is used to determine whether or not to generate the log call.
2684 // 1 (string): Format string. Access the string at argument index 2 2690 // 1 (string): Format string. Access the string at argument index 2
2685 // with '%2s' (see Logger::LogRuntime for all the formats). 2691 // with '%2s' (see Logger::LogRuntime for all the formats).
2686 // 2 (array): Arguments to the format string. 2692 // 2 (array): Arguments to the format string.
2693 ZoneList<Expression*>* args = expr->arguments();
2687 ASSERT_EQ(args->length(), 3); 2694 ASSERT_EQ(args->length(), 3);
2688 if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 2695 if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
2689 VisitForStackValue(args->at(1)); 2696 VisitForStackValue(args->at(1));
2690 VisitForStackValue(args->at(2)); 2697 VisitForStackValue(args->at(2));
2691 __ CallRuntime(Runtime::kLog, 2); 2698 __ CallRuntime(Runtime::kLog, 2);
2692 } 2699 }
2693 // Finally, we're expected to leave a value on the top of the stack. 2700 // Finally, we're expected to leave a value on the top of the stack.
2694 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 2701 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2695 context()->Plug(rax); 2702 context()->Plug(rax);
2696 } 2703 }
2697 2704
2698 2705
2699 void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { 2706 void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
2700 ASSERT(args->length() == 0); 2707 ASSERT(expr->arguments()->length() == 0);
2701 2708
2702 Label slow_allocate_heapnumber; 2709 Label slow_allocate_heapnumber;
2703 Label heapnumber_allocated; 2710 Label heapnumber_allocated;
2704 2711
2705 __ AllocateHeapNumber(rbx, rcx, &slow_allocate_heapnumber); 2712 __ AllocateHeapNumber(rbx, rcx, &slow_allocate_heapnumber);
2706 __ jmp(&heapnumber_allocated); 2713 __ jmp(&heapnumber_allocated);
2707 2714
2708 __ bind(&slow_allocate_heapnumber); 2715 __ bind(&slow_allocate_heapnumber);
2709 // Allocate a heap number. 2716 // Allocate a heap number.
2710 __ CallRuntime(Runtime::kNumberAlloc, 0); 2717 __ CallRuntime(Runtime::kNumberAlloc, 0);
(...skipping 23 matching lines...) Expand all
2734 __ cvtss2sd(xmm1, xmm1); 2741 __ cvtss2sd(xmm1, xmm1);
2735 __ xorps(xmm0, xmm1); 2742 __ xorps(xmm0, xmm1);
2736 __ subsd(xmm0, xmm1); 2743 __ subsd(xmm0, xmm1);
2737 __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0); 2744 __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0);
2738 2745
2739 __ movq(rax, rbx); 2746 __ movq(rax, rbx);
2740 context()->Plug(rax); 2747 context()->Plug(rax);
2741 } 2748 }
2742 2749
2743 2750
2744 void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { 2751 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
2745 // Load the arguments on the stack and call the stub. 2752 // Load the arguments on the stack and call the stub.
2746 SubStringStub stub; 2753 SubStringStub stub;
2754 ZoneList<Expression*>* args = expr->arguments();
2747 ASSERT(args->length() == 3); 2755 ASSERT(args->length() == 3);
2748 VisitForStackValue(args->at(0)); 2756 VisitForStackValue(args->at(0));
2749 VisitForStackValue(args->at(1)); 2757 VisitForStackValue(args->at(1));
2750 VisitForStackValue(args->at(2)); 2758 VisitForStackValue(args->at(2));
2751 __ CallStub(&stub); 2759 __ CallStub(&stub);
2752 context()->Plug(rax); 2760 context()->Plug(rax);
2753 } 2761 }
2754 2762
2755 2763
2756 void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { 2764 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
2757 // Load the arguments on the stack and call the stub. 2765 // Load the arguments on the stack and call the stub.
2758 RegExpExecStub stub; 2766 RegExpExecStub stub;
2767 ZoneList<Expression*>* args = expr->arguments();
2759 ASSERT(args->length() == 4); 2768 ASSERT(args->length() == 4);
2760 VisitForStackValue(args->at(0)); 2769 VisitForStackValue(args->at(0));
2761 VisitForStackValue(args->at(1)); 2770 VisitForStackValue(args->at(1));
2762 VisitForStackValue(args->at(2)); 2771 VisitForStackValue(args->at(2));
2763 VisitForStackValue(args->at(3)); 2772 VisitForStackValue(args->at(3));
2764 __ CallStub(&stub); 2773 __ CallStub(&stub);
2765 context()->Plug(rax); 2774 context()->Plug(rax);
2766 } 2775 }
2767 2776
2768 2777
2769 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { 2778 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
2779 ZoneList<Expression*>* args = expr->arguments();
2770 ASSERT(args->length() == 1); 2780 ASSERT(args->length() == 1);
2771 2781
2772 VisitForAccumulatorValue(args->at(0)); // Load the object. 2782 VisitForAccumulatorValue(args->at(0)); // Load the object.
2773 2783
2774 Label done; 2784 Label done;
2775 // If the object is a smi return the object. 2785 // If the object is a smi return the object.
2776 __ JumpIfSmi(rax, &done); 2786 __ JumpIfSmi(rax, &done);
2777 // If the object is not a value type, return the object. 2787 // If the object is not a value type, return the object.
2778 __ CmpObjectType(rax, JS_VALUE_TYPE, rbx); 2788 __ CmpObjectType(rax, JS_VALUE_TYPE, rbx);
2779 __ j(not_equal, &done); 2789 __ j(not_equal, &done);
2780 __ movq(rax, FieldOperand(rax, JSValue::kValueOffset)); 2790 __ movq(rax, FieldOperand(rax, JSValue::kValueOffset));
2781 2791
2782 __ bind(&done); 2792 __ bind(&done);
2783 context()->Plug(rax); 2793 context()->Plug(rax);
2784 } 2794 }
2785 2795
2786 2796
2787 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { 2797 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
2788 // Load the arguments on the stack and call the runtime function. 2798 // Load the arguments on the stack and call the runtime function.
2799 ZoneList<Expression*>* args = expr->arguments();
2789 ASSERT(args->length() == 2); 2800 ASSERT(args->length() == 2);
2790 VisitForStackValue(args->at(0)); 2801 VisitForStackValue(args->at(0));
2791 VisitForStackValue(args->at(1)); 2802 VisitForStackValue(args->at(1));
2792 MathPowStub stub; 2803 MathPowStub stub;
2793 __ CallStub(&stub); 2804 __ CallStub(&stub);
2794 context()->Plug(rax); 2805 context()->Plug(rax);
2795 } 2806 }
2796 2807
2797 2808
2798 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2809 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
2810 ZoneList<Expression*>* args = expr->arguments();
2799 ASSERT(args->length() == 2); 2811 ASSERT(args->length() == 2);
2800 2812
2801 VisitForStackValue(args->at(0)); // Load the object. 2813 VisitForStackValue(args->at(0)); // Load the object.
2802 VisitForAccumulatorValue(args->at(1)); // Load the value. 2814 VisitForAccumulatorValue(args->at(1)); // Load the value.
2803 __ pop(rbx); // rax = value. rbx = object. 2815 __ pop(rbx); // rax = value. rbx = object.
2804 2816
2805 Label done; 2817 Label done;
2806 // If the object is a smi, return the value. 2818 // If the object is a smi, return the value.
2807 __ JumpIfSmi(rbx, &done); 2819 __ JumpIfSmi(rbx, &done);
2808 2820
2809 // If the object is not a value type, return the value. 2821 // If the object is not a value type, return the value.
2810 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); 2822 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx);
2811 __ j(not_equal, &done); 2823 __ j(not_equal, &done);
2812 2824
2813 // Store the value. 2825 // Store the value.
2814 __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax); 2826 __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax);
2815 // Update the write barrier. Save the value as it will be 2827 // Update the write barrier. Save the value as it will be
2816 // overwritten by the write barrier code and is needed afterward. 2828 // overwritten by the write barrier code and is needed afterward.
2817 __ movq(rdx, rax); 2829 __ movq(rdx, rax);
2818 __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs); 2830 __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs);
2819 2831
2820 __ bind(&done); 2832 __ bind(&done);
2821 context()->Plug(rax); 2833 context()->Plug(rax);
2822 } 2834 }
2823 2835
2824 2836
2825 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { 2837 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
2838 ZoneList<Expression*>* args = expr->arguments();
2826 ASSERT_EQ(args->length(), 1); 2839 ASSERT_EQ(args->length(), 1);
2827 2840
2828 // Load the argument on the stack and call the stub. 2841 // Load the argument on the stack and call the stub.
2829 VisitForStackValue(args->at(0)); 2842 VisitForStackValue(args->at(0));
2830 2843
2831 NumberToStringStub stub; 2844 NumberToStringStub stub;
2832 __ CallStub(&stub); 2845 __ CallStub(&stub);
2833 context()->Plug(rax); 2846 context()->Plug(rax);
2834 } 2847 }
2835 2848
2836 2849
2837 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { 2850 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
2851 ZoneList<Expression*>* args = expr->arguments();
2838 ASSERT(args->length() == 1); 2852 ASSERT(args->length() == 1);
2839 2853
2840 VisitForAccumulatorValue(args->at(0)); 2854 VisitForAccumulatorValue(args->at(0));
2841 2855
2842 Label done; 2856 Label done;
2843 StringCharFromCodeGenerator generator(rax, rbx); 2857 StringCharFromCodeGenerator generator(rax, rbx);
2844 generator.GenerateFast(masm_); 2858 generator.GenerateFast(masm_);
2845 __ jmp(&done); 2859 __ jmp(&done);
2846 2860
2847 NopRuntimeCallHelper call_helper; 2861 NopRuntimeCallHelper call_helper;
2848 generator.GenerateSlow(masm_, call_helper); 2862 generator.GenerateSlow(masm_, call_helper);
2849 2863
2850 __ bind(&done); 2864 __ bind(&done);
2851 context()->Plug(rbx); 2865 context()->Plug(rbx);
2852 } 2866 }
2853 2867
2854 2868
2855 void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { 2869 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
2870 ZoneList<Expression*>* args = expr->arguments();
2856 ASSERT(args->length() == 2); 2871 ASSERT(args->length() == 2);
2857 2872
2858 VisitForStackValue(args->at(0)); 2873 VisitForStackValue(args->at(0));
2859 VisitForAccumulatorValue(args->at(1)); 2874 VisitForAccumulatorValue(args->at(1));
2860 2875
2861 Register object = rbx; 2876 Register object = rbx;
2862 Register index = rax; 2877 Register index = rax;
2863 Register scratch = rcx; 2878 Register scratch = rcx;
2864 Register result = rdx; 2879 Register result = rdx;
2865 2880
(...skipping 26 matching lines...) Expand all
2892 __ jmp(&done); 2907 __ jmp(&done);
2893 2908
2894 NopRuntimeCallHelper call_helper; 2909 NopRuntimeCallHelper call_helper;
2895 generator.GenerateSlow(masm_, call_helper); 2910 generator.GenerateSlow(masm_, call_helper);
2896 2911
2897 __ bind(&done); 2912 __ bind(&done);
2898 context()->Plug(result); 2913 context()->Plug(result);
2899 } 2914 }
2900 2915
2901 2916
2902 void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { 2917 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
2918 ZoneList<Expression*>* args = expr->arguments();
2903 ASSERT(args->length() == 2); 2919 ASSERT(args->length() == 2);
2904 2920
2905 VisitForStackValue(args->at(0)); 2921 VisitForStackValue(args->at(0));
2906 VisitForAccumulatorValue(args->at(1)); 2922 VisitForAccumulatorValue(args->at(1));
2907 2923
2908 Register object = rbx; 2924 Register object = rbx;
2909 Register index = rax; 2925 Register index = rax;
2910 Register scratch1 = rcx; 2926 Register scratch1 = rcx;
2911 Register scratch2 = rdx; 2927 Register scratch2 = rdx;
2912 Register result = rax; 2928 Register result = rax;
(...skipping 28 matching lines...) Expand all
2941 __ jmp(&done); 2957 __ jmp(&done);
2942 2958
2943 NopRuntimeCallHelper call_helper; 2959 NopRuntimeCallHelper call_helper;
2944 generator.GenerateSlow(masm_, call_helper); 2960 generator.GenerateSlow(masm_, call_helper);
2945 2961
2946 __ bind(&done); 2962 __ bind(&done);
2947 context()->Plug(result); 2963 context()->Plug(result);
2948 } 2964 }
2949 2965
2950 2966
2951 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { 2967 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
2968 ZoneList<Expression*>* args = expr->arguments();
2952 ASSERT_EQ(2, args->length()); 2969 ASSERT_EQ(2, args->length());
2953 2970
2954 VisitForStackValue(args->at(0)); 2971 VisitForStackValue(args->at(0));
2955 VisitForStackValue(args->at(1)); 2972 VisitForStackValue(args->at(1));
2956 2973
2957 StringAddStub stub(NO_STRING_ADD_FLAGS); 2974 StringAddStub stub(NO_STRING_ADD_FLAGS);
2958 __ CallStub(&stub); 2975 __ CallStub(&stub);
2959 context()->Plug(rax); 2976 context()->Plug(rax);
2960 } 2977 }
2961 2978
2962 2979
2963 void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { 2980 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
2981 ZoneList<Expression*>* args = expr->arguments();
2964 ASSERT_EQ(2, args->length()); 2982 ASSERT_EQ(2, args->length());
2965 2983
2966 VisitForStackValue(args->at(0)); 2984 VisitForStackValue(args->at(0));
2967 VisitForStackValue(args->at(1)); 2985 VisitForStackValue(args->at(1));
2968 2986
2969 StringCompareStub stub; 2987 StringCompareStub stub;
2970 __ CallStub(&stub); 2988 __ CallStub(&stub);
2971 context()->Plug(rax); 2989 context()->Plug(rax);
2972 } 2990 }
2973 2991
2974 2992
2975 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 2993 void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
2976 // Load the argument on the stack and call the stub. 2994 // Load the argument on the stack and call the stub.
2977 TranscendentalCacheStub stub(TranscendentalCache::SIN, 2995 TranscendentalCacheStub stub(TranscendentalCache::SIN,
2978 TranscendentalCacheStub::TAGGED); 2996 TranscendentalCacheStub::TAGGED);
2997 ZoneList<Expression*>* args = expr->arguments();
2979 ASSERT(args->length() == 1); 2998 ASSERT(args->length() == 1);
2980 VisitForStackValue(args->at(0)); 2999 VisitForStackValue(args->at(0));
2981 __ CallStub(&stub); 3000 __ CallStub(&stub);
2982 context()->Plug(rax); 3001 context()->Plug(rax);
2983 } 3002 }
2984 3003
2985 3004
2986 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 3005 void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
2987 // Load the argument on the stack and call the stub. 3006 // Load the argument on the stack and call the stub.
2988 TranscendentalCacheStub stub(TranscendentalCache::COS, 3007 TranscendentalCacheStub stub(TranscendentalCache::COS,
2989 TranscendentalCacheStub::TAGGED); 3008 TranscendentalCacheStub::TAGGED);
3009 ZoneList<Expression*>* args = expr->arguments();
2990 ASSERT(args->length() == 1); 3010 ASSERT(args->length() == 1);
2991 VisitForStackValue(args->at(0)); 3011 VisitForStackValue(args->at(0));
2992 __ CallStub(&stub); 3012 __ CallStub(&stub);
2993 context()->Plug(rax); 3013 context()->Plug(rax);
2994 } 3014 }
2995 3015
2996 3016
2997 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { 3017 void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
2998 // Load the argument on the stack and call the stub. 3018 // Load the argument on the stack and call the stub.
2999 TranscendentalCacheStub stub(TranscendentalCache::LOG, 3019 TranscendentalCacheStub stub(TranscendentalCache::LOG,
3000 TranscendentalCacheStub::TAGGED); 3020 TranscendentalCacheStub::TAGGED);
3021 ZoneList<Expression*>* args = expr->arguments();
3001 ASSERT(args->length() == 1); 3022 ASSERT(args->length() == 1);
3002 VisitForStackValue(args->at(0)); 3023 VisitForStackValue(args->at(0));
3003 __ CallStub(&stub); 3024 __ CallStub(&stub);
3004 context()->Plug(rax); 3025 context()->Plug(rax);
3005 } 3026 }
3006 3027
3007 3028
3008 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 3029 void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
3009 // Load the argument on the stack and call the runtime function. 3030 // Load the argument on the stack and call the runtime function.
3031 ZoneList<Expression*>* args = expr->arguments();
3010 ASSERT(args->length() == 1); 3032 ASSERT(args->length() == 1);
3011 VisitForStackValue(args->at(0)); 3033 VisitForStackValue(args->at(0));
3012 __ CallRuntime(Runtime::kMath_sqrt, 1); 3034 __ CallRuntime(Runtime::kMath_sqrt, 1);
3013 context()->Plug(rax); 3035 context()->Plug(rax);
3014 } 3036 }
3015 3037
3016 3038
3017 void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { 3039 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
3040 ZoneList<Expression*>* args = expr->arguments();
3018 ASSERT(args->length() >= 2); 3041 ASSERT(args->length() >= 2);
3019 3042
3020 int arg_count = args->length() - 2; // 2 ~ receiver and function. 3043 int arg_count = args->length() - 2; // 2 ~ receiver and function.
3021 for (int i = 0; i < arg_count + 1; i++) { 3044 for (int i = 0; i < arg_count + 1; i++) {
3022 VisitForStackValue(args->at(i)); 3045 VisitForStackValue(args->at(i));
3023 } 3046 }
3024 VisitForAccumulatorValue(args->last()); // Function. 3047 VisitForAccumulatorValue(args->last()); // Function.
3025 3048
3026 // InvokeFunction requires the function in rdi. Move it in there. 3049 // InvokeFunction requires the function in rdi. Move it in there.
3027 __ movq(rdi, result_register()); 3050 __ movq(rdi, result_register());
3028 ParameterCount count(arg_count); 3051 ParameterCount count(arg_count);
3029 __ InvokeFunction(rdi, count, CALL_FUNCTION, 3052 __ InvokeFunction(rdi, count, CALL_FUNCTION,
3030 NullCallWrapper(), CALL_AS_METHOD); 3053 NullCallWrapper(), CALL_AS_METHOD);
3031 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3054 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3032 context()->Plug(rax); 3055 context()->Plug(rax);
3033 } 3056 }
3034 3057
3035 3058
3036 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 3059 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3037 RegExpConstructResultStub stub; 3060 RegExpConstructResultStub stub;
3061 ZoneList<Expression*>* args = expr->arguments();
3038 ASSERT(args->length() == 3); 3062 ASSERT(args->length() == 3);
3039 VisitForStackValue(args->at(0)); 3063 VisitForStackValue(args->at(0));
3040 VisitForStackValue(args->at(1)); 3064 VisitForStackValue(args->at(1));
3041 VisitForStackValue(args->at(2)); 3065 VisitForStackValue(args->at(2));
3042 __ CallStub(&stub); 3066 __ CallStub(&stub);
3043 context()->Plug(rax); 3067 context()->Plug(rax);
3044 } 3068 }
3045 3069
3046 3070
3047 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { 3071 void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
3072 ZoneList<Expression*>* args = expr->arguments();
3048 ASSERT(args->length() == 3); 3073 ASSERT(args->length() == 3);
3049 VisitForStackValue(args->at(0)); 3074 VisitForStackValue(args->at(0));
3050 VisitForStackValue(args->at(1)); 3075 VisitForStackValue(args->at(1));
3051 VisitForStackValue(args->at(2)); 3076 VisitForStackValue(args->at(2));
3052 Label done; 3077 Label done;
3053 Label slow_case; 3078 Label slow_case;
3054 Register object = rax; 3079 Register object = rax;
3055 Register index_1 = rbx; 3080 Register index_1 = rbx;
3056 Register index_2 = rcx; 3081 Register index_2 = rcx;
3057 Register elements = rdi; 3082 Register elements = rdi;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
3132 __ jmp(&done); 3157 __ jmp(&done);
3133 3158
3134 __ bind(&slow_case); 3159 __ bind(&slow_case);
3135 __ CallRuntime(Runtime::kSwapElements, 3); 3160 __ CallRuntime(Runtime::kSwapElements, 3);
3136 3161
3137 __ bind(&done); 3162 __ bind(&done);
3138 context()->Plug(rax); 3163 context()->Plug(rax);
3139 } 3164 }
3140 3165
3141 3166
3142 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { 3167 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3168 ZoneList<Expression*>* args = expr->arguments();
3143 ASSERT_EQ(2, args->length()); 3169 ASSERT_EQ(2, args->length());
3144 3170
3145 ASSERT_NE(NULL, args->at(0)->AsLiteral()); 3171 ASSERT_NE(NULL, args->at(0)->AsLiteral());
3146 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 3172 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
3147 3173
3148 Handle<FixedArray> jsfunction_result_caches( 3174 Handle<FixedArray> jsfunction_result_caches(
3149 isolate()->global_context()->jsfunction_result_caches()); 3175 isolate()->global_context()->jsfunction_result_caches());
3150 if (jsfunction_result_caches->length() <= cache_id) { 3176 if (jsfunction_result_caches->length() <= cache_id) {
3151 __ Abort("Attempt to use undefined cache."); 3177 __ Abort("Attempt to use undefined cache.");
3152 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 3178 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
3188 // Call runtime to perform the lookup. 3214 // Call runtime to perform the lookup.
3189 __ push(cache); 3215 __ push(cache);
3190 __ push(key); 3216 __ push(key);
3191 __ CallRuntime(Runtime::kGetFromCache, 2); 3217 __ CallRuntime(Runtime::kGetFromCache, 2);
3192 3218
3193 __ bind(&done); 3219 __ bind(&done);
3194 context()->Plug(rax); 3220 context()->Plug(rax);
3195 } 3221 }
3196 3222
3197 3223
3198 void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) { 3224 void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
3225 ZoneList<Expression*>* args = expr->arguments();
3199 ASSERT_EQ(2, args->length()); 3226 ASSERT_EQ(2, args->length());
3200 3227
3201 Register right = rax; 3228 Register right = rax;
3202 Register left = rbx; 3229 Register left = rbx;
3203 Register tmp = rcx; 3230 Register tmp = rcx;
3204 3231
3205 VisitForStackValue(args->at(0)); 3232 VisitForStackValue(args->at(0));
3206 VisitForAccumulatorValue(args->at(1)); 3233 VisitForAccumulatorValue(args->at(1));
3207 __ pop(left); 3234 __ pop(left);
3208 3235
(...skipping 17 matching lines...) Expand all
3226 __ Move(rax, isolate()->factory()->false_value()); 3253 __ Move(rax, isolate()->factory()->false_value());
3227 __ jmp(&done, Label::kNear); 3254 __ jmp(&done, Label::kNear);
3228 __ bind(&ok); 3255 __ bind(&ok);
3229 __ Move(rax, isolate()->factory()->true_value()); 3256 __ Move(rax, isolate()->factory()->true_value());
3230 __ bind(&done); 3257 __ bind(&done);
3231 3258
3232 context()->Plug(rax); 3259 context()->Plug(rax);
3233 } 3260 }
3234 3261
3235 3262
3236 void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { 3263 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3264 ZoneList<Expression*>* args = expr->arguments();
3237 ASSERT(args->length() == 1); 3265 ASSERT(args->length() == 1);
3238 3266
3239 VisitForAccumulatorValue(args->at(0)); 3267 VisitForAccumulatorValue(args->at(0));
3240 3268
3241 Label materialize_true, materialize_false; 3269 Label materialize_true, materialize_false;
3242 Label* if_true = NULL; 3270 Label* if_true = NULL;
3243 Label* if_false = NULL; 3271 Label* if_false = NULL;
3244 Label* fall_through = NULL; 3272 Label* fall_through = NULL;
3245 context()->PrepareTest(&materialize_true, &materialize_false, 3273 context()->PrepareTest(&materialize_true, &materialize_false,
3246 &if_true, &if_false, &fall_through); 3274 &if_true, &if_false, &fall_through);
3247 3275
3248 __ testl(FieldOperand(rax, String::kHashFieldOffset), 3276 __ testl(FieldOperand(rax, String::kHashFieldOffset),
3249 Immediate(String::kContainsCachedArrayIndexMask)); 3277 Immediate(String::kContainsCachedArrayIndexMask));
3250 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 3278 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3251 __ j(zero, if_true); 3279 __ j(zero, if_true);
3252 __ jmp(if_false); 3280 __ jmp(if_false);
3253 3281
3254 context()->Plug(if_true, if_false); 3282 context()->Plug(if_true, if_false);
3255 } 3283 }
3256 3284
3257 3285
3258 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 3286 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3287 ZoneList<Expression*>* args = expr->arguments();
3259 ASSERT(args->length() == 1); 3288 ASSERT(args->length() == 1);
3260 VisitForAccumulatorValue(args->at(0)); 3289 VisitForAccumulatorValue(args->at(0));
3261 3290
3262 if (FLAG_debug_code) { 3291 if (FLAG_debug_code) {
3263 __ AbortIfNotString(rax); 3292 __ AbortIfNotString(rax);
3264 } 3293 }
3265 3294
3266 __ movl(rax, FieldOperand(rax, String::kHashFieldOffset)); 3295 __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
3267 ASSERT(String::kHashShift >= kSmiTagSize); 3296 ASSERT(String::kHashShift >= kSmiTagSize);
3268 __ IndexFromHash(rax, rax); 3297 __ IndexFromHash(rax, rax);
3269 3298
3270 context()->Plug(rax); 3299 context()->Plug(rax);
3271 } 3300 }
3272 3301
3273 3302
3274 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { 3303 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
3275 Label bailout, return_result, done, one_char_separator, long_separator, 3304 Label bailout, return_result, done, one_char_separator, long_separator,
3276 non_trivial_array, not_size_one_array, loop, 3305 non_trivial_array, not_size_one_array, loop,
3277 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; 3306 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
3307 ZoneList<Expression*>* args = expr->arguments();
3278 ASSERT(args->length() == 2); 3308 ASSERT(args->length() == 2);
3279 // We will leave the separator on the stack until the end of the function. 3309 // We will leave the separator on the stack until the end of the function.
3280 VisitForStackValue(args->at(1)); 3310 VisitForStackValue(args->at(1));
3281 // Load this to rax (= array) 3311 // Load this to rax (= array)
3282 VisitForAccumulatorValue(args->at(0)); 3312 VisitForAccumulatorValue(args->at(0));
3283 // All aliases of the same register have disjoint lifetimes. 3313 // All aliases of the same register have disjoint lifetimes.
3284 Register array = rax; 3314 Register array = rax;
3285 Register elements = no_reg; // Will be rax. 3315 Register elements = no_reg; // Will be rax.
3286 3316
3287 Register index = rdx; 3317 Register index = rdx;
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
3646 context()->Plug(Heap::kUndefinedValueRootIndex); 3676 context()->Plug(Heap::kUndefinedValueRootIndex);
3647 break; 3677 break;
3648 } 3678 }
3649 3679
3650 case Token::NOT: { 3680 case Token::NOT: {
3651 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 3681 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
3652 if (context()->IsEffect()) { 3682 if (context()->IsEffect()) {
3653 // Unary NOT has no side effects so it's only necessary to visit the 3683 // Unary NOT has no side effects so it's only necessary to visit the
3654 // subexpression. Match the optimizing compiler by not branching. 3684 // subexpression. Match the optimizing compiler by not branching.
3655 VisitForEffect(expr->expression()); 3685 VisitForEffect(expr->expression());
3686 } else if (context()->IsTest()) {
3687 const TestContext* test = TestContext::cast(context());
3688 // The labels are swapped for the recursive call.
3689 VisitForControl(expr->expression(),
3690 test->false_label(),
3691 test->true_label(),
3692 test->fall_through());
3693 context()->Plug(test->true_label(), test->false_label());
3656 } else { 3694 } else {
3657 Label materialize_true, materialize_false; 3695 // We handle value contexts explicitly rather than simply visiting
3658 Label* if_true = NULL; 3696 // for control and plugging the control flow into the context,
3659 Label* if_false = NULL; 3697 // because we need to prepare a pair of extra administrative AST ids
3660 Label* fall_through = NULL; 3698 // for the optimizing compiler.
3661 // Notice that the labels are swapped. 3699 ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
3662 context()->PrepareTest(&materialize_true, &materialize_false, 3700 Label materialize_true, materialize_false, done;
3663 &if_false, &if_true, &fall_through); 3701 VisitForControl(expr->expression(),
3664 if (context()->IsTest()) ForwardBailoutToChild(expr); 3702 &materialize_false,
3665 VisitForControl(expr->expression(), if_true, if_false, fall_through); 3703 &materialize_true,
3666 context()->Plug(if_false, if_true); // Labels swapped. 3704 &materialize_true);
3705 __ bind(&materialize_true);
3706 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
3707 if (context()->IsAccumulatorValue()) {
3708 __ LoadRoot(rax, Heap::kTrueValueRootIndex);
3709 } else {
3710 __ PushRoot(Heap::kTrueValueRootIndex);
3711 }
3712 __ jmp(&done, Label::kNear);
3713 __ bind(&materialize_false);
3714 PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
3715 if (context()->IsAccumulatorValue()) {
3716 __ LoadRoot(rax, Heap::kFalseValueRootIndex);
3717 } else {
3718 __ PushRoot(Heap::kFalseValueRootIndex);
3719 }
3720 __ bind(&done);
3667 } 3721 }
3668 break; 3722 break;
3669 } 3723 }
3670 3724
3671 case Token::TYPEOF: { 3725 case Token::TYPEOF: {
3672 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 3726 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
3673 { StackValueContext context(this); 3727 { StackValueContext context(this);
3674 VisitForTypeofValue(expr->expression()); 3728 VisitForTypeofValue(expr->expression());
3675 } 3729 }
3676 __ CallRuntime(Runtime::kTypeof, 1); 3730 __ CallRuntime(Runtime::kTypeof, 1);
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
3928 __ bind(&slow); 3982 __ bind(&slow);
3929 __ push(rsi); 3983 __ push(rsi);
3930 __ Push(proxy->name()); 3984 __ Push(proxy->name());
3931 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3985 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3932 PrepareForBailout(expr, TOS_REG); 3986 PrepareForBailout(expr, TOS_REG);
3933 __ bind(&done); 3987 __ bind(&done);
3934 3988
3935 context()->Plug(rax); 3989 context()->Plug(rax);
3936 } else { 3990 } else {
3937 // This expression cannot throw a reference error at the top level. 3991 // This expression cannot throw a reference error at the top level.
3938 VisitInCurrentContext(expr); 3992 VisitInDuplicateContext(expr);
3939 } 3993 }
3940 } 3994 }
3941 3995
3942 3996
3943 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, 3997 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
3998 Expression* sub_expr,
3944 Handle<String> check) { 3999 Handle<String> check) {
3945 Label materialize_true, materialize_false; 4000 Label materialize_true, materialize_false;
3946 Label* if_true = NULL; 4001 Label* if_true = NULL;
3947 Label* if_false = NULL; 4002 Label* if_false = NULL;
3948 Label* fall_through = NULL; 4003 Label* fall_through = NULL;
3949 context()->PrepareTest(&materialize_true, &materialize_false, 4004 context()->PrepareTest(&materialize_true, &materialize_false,
3950 &if_true, &if_false, &fall_through); 4005 &if_true, &if_false, &fall_through);
3951 4006
3952 { AccumulatorValueContext context(this); 4007 { AccumulatorValueContext context(this);
3953 VisitForTypeofValue(expr); 4008 VisitForTypeofValue(sub_expr);
3954 } 4009 }
3955 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4010 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3956 4011
3957 if (check->Equals(isolate()->heap()->number_symbol())) { 4012 if (check->Equals(isolate()->heap()->number_symbol())) {
3958 __ JumpIfSmi(rax, if_true); 4013 __ JumpIfSmi(rax, if_true);
3959 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); 4014 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
3960 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); 4015 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
3961 Split(equal, if_true, if_false, fall_through); 4016 Split(equal, if_true, if_false, fall_through);
3962 } else if (check->Equals(isolate()->heap()->string_symbol())) { 4017 } else if (check->Equals(isolate()->heap()->string_symbol())) {
3963 __ JumpIfSmi(rax, if_false); 4018 __ JumpIfSmi(rax, if_false);
3964 // Check for undetectable objects => false. 4019 // Check for undetectable objects => false.
3965 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); 4020 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
4029 Label* fall_through = NULL; 4084 Label* fall_through = NULL;
4030 context()->PrepareTest(&materialize_true, &materialize_false, 4085 context()->PrepareTest(&materialize_true, &materialize_false,
4031 &if_true, &if_false, &fall_through); 4086 &if_true, &if_false, &fall_through);
4032 4087
4033 Token::Value op = expr->op(); 4088 Token::Value op = expr->op();
4034 VisitForStackValue(expr->left()); 4089 VisitForStackValue(expr->left());
4035 switch (op) { 4090 switch (op) {
4036 case Token::IN: 4091 case Token::IN:
4037 VisitForStackValue(expr->right()); 4092 VisitForStackValue(expr->right());
4038 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 4093 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4039 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 4094 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4040 __ CompareRoot(rax, Heap::kTrueValueRootIndex); 4095 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
4041 Split(equal, if_true, if_false, fall_through); 4096 Split(equal, if_true, if_false, fall_through);
4042 break; 4097 break;
4043 4098
4044 case Token::INSTANCEOF: { 4099 case Token::INSTANCEOF: {
4045 VisitForStackValue(expr->right()); 4100 VisitForStackValue(expr->right());
4046 InstanceofStub stub(InstanceofStub::kNoFlags); 4101 InstanceofStub stub(InstanceofStub::kNoFlags);
4047 __ CallStub(&stub); 4102 __ CallStub(&stub);
4048 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4103 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4049 __ testq(rax, rax); 4104 __ testq(rax, rax);
4050 // The stub returns 0 for true. 4105 // The stub returns 0 for true.
4051 Split(zero, if_true, if_false, fall_through); 4106 Split(zero, if_true, if_false, fall_through);
4052 break; 4107 break;
4053 } 4108 }
4054 4109
4055 default: { 4110 default: {
4056 VisitForAccumulatorValue(expr->right()); 4111 VisitForAccumulatorValue(expr->right());
4057 Condition cc = no_condition; 4112 Condition cc = no_condition;
4058 switch (op) { 4113 switch (op) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4090 Split(cc, if_true, if_false, NULL); 4145 Split(cc, if_true, if_false, NULL);
4091 __ bind(&slow_case); 4146 __ bind(&slow_case);
4092 } 4147 }
4093 4148
4094 // Record position and call the compare IC. 4149 // Record position and call the compare IC.
4095 SetSourcePosition(expr->position()); 4150 SetSourcePosition(expr->position());
4096 Handle<Code> ic = CompareIC::GetUninitialized(op); 4151 Handle<Code> ic = CompareIC::GetUninitialized(op);
4097 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); 4152 __ call(ic, RelocInfo::CODE_TARGET, expr->id());
4098 patch_site.EmitPatchInfo(); 4153 patch_site.EmitPatchInfo();
4099 4154
4100 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4155 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4101 __ testq(rax, rax); 4156 __ testq(rax, rax);
4102 Split(cc, if_true, if_false, fall_through); 4157 Split(cc, if_true, if_false, fall_through);
4103 } 4158 }
4104 } 4159 }
4105 4160
4106 // Convert the result of the comparison into one expected for this 4161 // Convert the result of the comparison into one expected for this
4107 // expression's context. 4162 // expression's context.
4108 context()->Plug(if_true, if_false); 4163 context()->Plug(if_true, if_false);
4109 } 4164 }
4110 4165
4111 4166
4112 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, 4167 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
4113 Expression* sub_expr, 4168 Expression* sub_expr,
4114 NilValue nil) { 4169 NilValue nil) {
4115 Label materialize_true, materialize_false; 4170 Label materialize_true, materialize_false;
4116 Label* if_true = NULL; 4171 Label* if_true = NULL;
4117 Label* if_false = NULL; 4172 Label* if_false = NULL;
4118 Label* fall_through = NULL; 4173 Label* fall_through = NULL;
4119 context()->PrepareTest(&materialize_true, &materialize_false, 4174 context()->PrepareTest(&materialize_true, &materialize_false,
4120 &if_true, &if_false, &fall_through); 4175 &if_true, &if_false, &fall_through);
4121 4176
4122 VisitForAccumulatorValue(sub_expr); 4177 VisitForAccumulatorValue(sub_expr);
4123 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4178 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4124 Heap::RootListIndex nil_value = nil == kNullValue ? 4179 Heap::RootListIndex nil_value = nil == kNullValue ?
4125 Heap::kNullValueRootIndex : 4180 Heap::kNullValueRootIndex :
4126 Heap::kUndefinedValueRootIndex; 4181 Heap::kUndefinedValueRootIndex;
4127 __ CompareRoot(rax, nil_value); 4182 __ CompareRoot(rax, nil_value);
4128 if (expr->op() == Token::EQ_STRICT) { 4183 if (expr->op() == Token::EQ_STRICT) {
4129 Split(equal, if_true, if_false, fall_through); 4184 Split(equal, if_true, if_false, fall_through);
4130 } else { 4185 } else {
4131 Heap::RootListIndex other_nil_value = nil == kNullValue ? 4186 Heap::RootListIndex other_nil_value = nil == kNullValue ?
4132 Heap::kUndefinedValueRootIndex : 4187 Heap::kUndefinedValueRootIndex :
4133 Heap::kNullValueRootIndex; 4188 Heap::kNullValueRootIndex;
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
4249 *context_length = 0; 4304 *context_length = 0;
4250 return previous_; 4305 return previous_;
4251 } 4306 }
4252 4307
4253 4308
4254 #undef __ 4309 #undef __
4255 4310
4256 } } // namespace v8::internal 4311 } } // namespace v8::internal
4257 4312
4258 #endif // V8_TARGET_ARCH_X64 4313 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/mips/full-codegen-mips.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698