OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |