| 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 1454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1465 __ movq(rdx, Operand(rsp, 0)); | 1465 __ movq(rdx, Operand(rsp, 0)); |
| 1466 __ push(rax); | 1466 __ push(rax); |
| 1467 } else { | 1467 } else { |
| 1468 VisitForStackValue(property->obj()); | 1468 VisitForStackValue(property->obj()); |
| 1469 VisitForStackValue(property->key()); | 1469 VisitForStackValue(property->key()); |
| 1470 } | 1470 } |
| 1471 break; | 1471 break; |
| 1472 } | 1472 } |
| 1473 } | 1473 } |
| 1474 | 1474 |
| 1475 // For compound assignments we need another deoptimization point after the |
| 1476 // variable/property load. |
| 1475 if (expr->is_compound()) { | 1477 if (expr->is_compound()) { |
| 1476 { AccumulatorValueContext context(this); | 1478 { AccumulatorValueContext context(this); |
| 1477 switch (assign_type) { | 1479 switch (assign_type) { |
| 1478 case VARIABLE: | 1480 case VARIABLE: |
| 1479 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); | 1481 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); |
| 1482 PrepareForBailout(expr->target(), TOS_REG); |
| 1480 break; | 1483 break; |
| 1481 case NAMED_PROPERTY: | 1484 case NAMED_PROPERTY: |
| 1482 EmitNamedPropertyLoad(property); | 1485 EmitNamedPropertyLoad(property); |
| 1486 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); |
| 1483 break; | 1487 break; |
| 1484 case KEYED_PROPERTY: | 1488 case KEYED_PROPERTY: |
| 1485 EmitKeyedPropertyLoad(property); | 1489 EmitKeyedPropertyLoad(property); |
| 1490 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); |
| 1486 break; | 1491 break; |
| 1487 } | 1492 } |
| 1488 } | 1493 } |
| 1489 | 1494 |
| 1490 // For property compound assignments we need another deoptimization | |
| 1491 // point after the property load. | |
| 1492 if (property != NULL) { | |
| 1493 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | |
| 1494 } | |
| 1495 | |
| 1496 Token::Value op = expr->binary_op(); | 1495 Token::Value op = expr->binary_op(); |
| 1497 __ push(rax); // Left operand goes on the stack. | 1496 __ push(rax); // Left operand goes on the stack. |
| 1498 VisitForAccumulatorValue(expr->value()); | 1497 VisitForAccumulatorValue(expr->value()); |
| 1499 | 1498 |
| 1500 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1499 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
| 1501 ? OVERWRITE_RIGHT | 1500 ? OVERWRITE_RIGHT |
| 1502 : NO_OVERWRITE; | 1501 : NO_OVERWRITE; |
| 1503 SetSourcePosition(expr->position() + 1); | 1502 SetSourcePosition(expr->position() + 1); |
| 1504 AccumulatorValueContext context(this); | 1503 AccumulatorValueContext context(this); |
| 1505 if (ShouldInlineSmiCase(op)) { | 1504 if (ShouldInlineSmiCase(op)) { |
| (...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2097 } | 2096 } |
| 2098 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 2097 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
| 2099 } else { | 2098 } else { |
| 2100 // Call to a keyed property. | 2099 // Call to a keyed property. |
| 2101 { PreservePositionScope scope(masm()->positions_recorder()); | 2100 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2102 VisitForStackValue(prop->obj()); | 2101 VisitForStackValue(prop->obj()); |
| 2103 } | 2102 } |
| 2104 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2103 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
| 2105 } | 2104 } |
| 2106 } else { | 2105 } else { |
| 2107 // Call to some other expression. If the expression is an anonymous | |
| 2108 // function literal not called in a loop, mark it as one that should | |
| 2109 // also use the full code generator. | |
| 2110 FunctionLiteral* lit = fun->AsFunctionLiteral(); | |
| 2111 if (lit != NULL && | |
| 2112 lit->name()->Equals(isolate()->heap()->empty_string()) && | |
| 2113 loop_depth() == 0) { | |
| 2114 lit->set_try_full_codegen(true); | |
| 2115 } | |
| 2116 { PreservePositionScope scope(masm()->positions_recorder()); | 2106 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2117 VisitForStackValue(fun); | 2107 VisitForStackValue(fun); |
| 2118 } | 2108 } |
| 2119 // Load global receiver object. | 2109 // Load global receiver object. |
| 2120 __ movq(rbx, GlobalObjectOperand()); | 2110 __ movq(rbx, GlobalObjectOperand()); |
| 2121 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); | 2111 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); |
| 2122 // Emit function call. | 2112 // Emit function call. |
| 2123 EmitCallWithStub(expr); | 2113 EmitCallWithStub(expr); |
| 2124 } | 2114 } |
| 2125 | 2115 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2284 | 2274 |
| 2285 VisitForAccumulatorValue(args->at(0)); | 2275 VisitForAccumulatorValue(args->at(0)); |
| 2286 | 2276 |
| 2287 Label materialize_true, materialize_false; | 2277 Label materialize_true, materialize_false; |
| 2288 Label* if_true = NULL; | 2278 Label* if_true = NULL; |
| 2289 Label* if_false = NULL; | 2279 Label* if_false = NULL; |
| 2290 Label* fall_through = NULL; | 2280 Label* fall_through = NULL; |
| 2291 context()->PrepareTest(&materialize_true, &materialize_false, | 2281 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2292 &if_true, &if_false, &fall_through); | 2282 &if_true, &if_false, &fall_through); |
| 2293 | 2283 |
| 2294 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only | 2284 if (FLAG_debug_code) __ AbortIfSmi(rax); |
| 2295 // used in a few functions in runtime.js which should not normally be hit by | 2285 |
| 2296 // this compiler. | 2286 // Check whether this map has already been checked to be safe for default |
| 2287 // valueOf. |
| 2288 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
| 2289 __ testb(FieldOperand(rbx, Map::kBitField2Offset), |
| 2290 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
| 2291 __ j(not_zero, if_true); |
| 2292 |
| 2293 // Check for fast case object. Generate false result for slow case object. |
| 2294 __ movq(rcx, FieldOperand(rax, JSObject::kPropertiesOffset)); |
| 2295 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); |
| 2296 __ CompareRoot(rcx, Heap::kHashTableMapRootIndex); |
| 2297 __ j(equal, if_false); |
| 2298 |
| 2299 // Look for valueOf symbol in the descriptor array, and indicate false if |
| 2300 // found. The type is not checked, so if it is a transition it is a false |
| 2301 // negative. |
| 2302 __ movq(rbx, FieldOperand(rbx, Map::kInstanceDescriptorsOffset)); |
| 2303 __ movq(rcx, FieldOperand(rbx, FixedArray::kLengthOffset)); |
| 2304 // rbx: descriptor array |
| 2305 // rcx: length of descriptor array |
| 2306 // Calculate the end of the descriptor array. |
| 2307 SmiIndex index = masm_->SmiToIndex(rdx, rcx, kPointerSizeLog2); |
| 2308 __ lea(rcx, |
| 2309 Operand( |
| 2310 rbx, index.reg, index.scale, FixedArray::kHeaderSize)); |
| 2311 // Calculate location of the first key name. |
| 2312 __ addq(rbx, |
| 2313 Immediate(FixedArray::kHeaderSize + |
| 2314 DescriptorArray::kFirstIndex * kPointerSize)); |
| 2315 // Loop through all the keys in the descriptor array. If one of these is the |
| 2316 // symbol valueOf the result is false. |
| 2317 Label entry, loop; |
| 2318 __ jmp(&entry); |
| 2319 __ bind(&loop); |
| 2320 __ movq(rdx, FieldOperand(rbx, 0)); |
| 2321 __ Cmp(rdx, FACTORY->value_of_symbol()); |
| 2322 __ j(equal, if_false); |
| 2323 __ addq(rbx, Immediate(kPointerSize)); |
| 2324 __ bind(&entry); |
| 2325 __ cmpq(rbx, rcx); |
| 2326 __ j(not_equal, &loop); |
| 2327 |
| 2328 // Reload map as register rbx was used as temporary above. |
| 2329 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
| 2330 |
| 2331 // If a valueOf property is not found on the object check that it's |
| 2332 // prototype is the un-modified String prototype. If not result is false. |
| 2333 __ movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset)); |
| 2334 __ testq(rcx, Immediate(kSmiTagMask)); |
| 2335 __ j(zero, if_false); |
| 2336 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); |
| 2337 __ movq(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 2338 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalContextOffset)); |
| 2339 __ cmpq(rcx, |
| 2340 ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
| 2341 __ j(not_equal, if_false); |
| 2342 // Set the bit in the map to indicate that it has been checked safe for |
| 2343 // default valueOf and set true result. |
| 2344 __ or_(FieldOperand(rbx, Map::kBitField2Offset), |
| 2345 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
| 2346 __ jmp(if_true); |
| 2347 |
| 2297 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2348 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 2298 __ jmp(if_false); | |
| 2299 context()->Plug(if_true, if_false); | 2349 context()->Plug(if_true, if_false); |
| 2300 } | 2350 } |
| 2301 | 2351 |
| 2302 | 2352 |
| 2303 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { | 2353 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { |
| 2304 ASSERT(args->length() == 1); | 2354 ASSERT(args->length() == 1); |
| 2305 | 2355 |
| 2306 VisitForAccumulatorValue(args->at(0)); | 2356 VisitForAccumulatorValue(args->at(0)); |
| 2307 | 2357 |
| 2308 Label materialize_true, materialize_false; | 2358 Label materialize_true, materialize_false; |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2542 | 2592 |
| 2543 __ bind(&slow_allocate_heapnumber); | 2593 __ bind(&slow_allocate_heapnumber); |
| 2544 // Allocate a heap number. | 2594 // Allocate a heap number. |
| 2545 __ CallRuntime(Runtime::kNumberAlloc, 0); | 2595 __ CallRuntime(Runtime::kNumberAlloc, 0); |
| 2546 __ movq(rbx, rax); | 2596 __ movq(rbx, rax); |
| 2547 | 2597 |
| 2548 __ bind(&heapnumber_allocated); | 2598 __ bind(&heapnumber_allocated); |
| 2549 | 2599 |
| 2550 // Return a random uint32 number in rax. | 2600 // Return a random uint32 number in rax. |
| 2551 // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs. | 2601 // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs. |
| 2552 __ PrepareCallCFunction(0); | 2602 __ PrepareCallCFunction(1); |
| 2553 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 0); | 2603 #ifdef _WIN64 |
| 2604 __ LoadAddress(rcx, ExternalReference::isolate_address()); |
| 2605 #else |
| 2606 __ LoadAddress(rdi, ExternalReference::isolate_address()); |
| 2607 #endif |
| 2608 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); |
| 2554 | 2609 |
| 2555 // Convert 32 random bits in rax to 0.(32 random bits) in a double | 2610 // Convert 32 random bits in rax to 0.(32 random bits) in a double |
| 2556 // by computing: | 2611 // by computing: |
| 2557 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | 2612 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). |
| 2558 __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. | 2613 __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. |
| 2559 __ movd(xmm1, rcx); | 2614 __ movd(xmm1, rcx); |
| 2560 __ movd(xmm0, rax); | 2615 __ movd(xmm0, rax); |
| 2561 __ cvtss2sd(xmm1, xmm1); | 2616 __ cvtss2sd(xmm1, xmm1); |
| 2562 __ xorpd(xmm0, xmm1); | 2617 __ xorpd(xmm0, xmm1); |
| 2563 __ subsd(xmm0, xmm1); | 2618 __ subsd(xmm0, xmm1); |
| (...skipping 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3588 VisitForStackValue(prop->obj()); | 3643 VisitForStackValue(prop->obj()); |
| 3589 VisitForAccumulatorValue(prop->key()); | 3644 VisitForAccumulatorValue(prop->key()); |
| 3590 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack | 3645 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack |
| 3591 __ push(rax); // Copy of key, needed for later store. | 3646 __ push(rax); // Copy of key, needed for later store. |
| 3592 EmitKeyedPropertyLoad(prop); | 3647 EmitKeyedPropertyLoad(prop); |
| 3593 } | 3648 } |
| 3594 } | 3649 } |
| 3595 | 3650 |
| 3596 // We need a second deoptimization point after loading the value | 3651 // We need a second deoptimization point after loading the value |
| 3597 // in case evaluating the property load my have a side effect. | 3652 // in case evaluating the property load my have a side effect. |
| 3598 PrepareForBailout(expr->increment(), TOS_REG); | 3653 if (assign_type == VARIABLE) { |
| 3654 PrepareForBailout(expr->expression(), TOS_REG); |
| 3655 } else { |
| 3656 PrepareForBailout(expr->increment(), TOS_REG); |
| 3657 } |
| 3599 | 3658 |
| 3600 // Call ToNumber only if operand is not a smi. | 3659 // Call ToNumber only if operand is not a smi. |
| 3601 NearLabel no_conversion; | 3660 NearLabel no_conversion; |
| 3602 Condition is_smi; | 3661 Condition is_smi; |
| 3603 is_smi = masm_->CheckSmi(rax); | 3662 is_smi = masm_->CheckSmi(rax); |
| 3604 __ j(is_smi, &no_conversion); | 3663 __ j(is_smi, &no_conversion); |
| 3605 ToNumberStub convert_stub; | 3664 ToNumberStub convert_stub; |
| 3606 __ CallStub(&convert_stub); | 3665 __ CallStub(&convert_stub); |
| 3607 __ bind(&no_conversion); | 3666 __ bind(&no_conversion); |
| 3608 | 3667 |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4113 __ ret(0); | 4172 __ ret(0); |
| 4114 } | 4173 } |
| 4115 | 4174 |
| 4116 | 4175 |
| 4117 #undef __ | 4176 #undef __ |
| 4118 | 4177 |
| 4119 | 4178 |
| 4120 } } // namespace v8::internal | 4179 } } // namespace v8::internal |
| 4121 | 4180 |
| 4122 #endif // V8_TARGET_ARCH_X64 | 4181 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |