| 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. | |
| 1477 if (expr->is_compound()) { | 1475 if (expr->is_compound()) { |
| 1478 { AccumulatorValueContext context(this); | 1476 { AccumulatorValueContext context(this); |
| 1479 switch (assign_type) { | 1477 switch (assign_type) { |
| 1480 case VARIABLE: | 1478 case VARIABLE: |
| 1481 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); | 1479 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); |
| 1482 PrepareForBailout(expr->target(), TOS_REG); | |
| 1483 break; | 1480 break; |
| 1484 case NAMED_PROPERTY: | 1481 case NAMED_PROPERTY: |
| 1485 EmitNamedPropertyLoad(property); | 1482 EmitNamedPropertyLoad(property); |
| 1486 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | |
| 1487 break; | 1483 break; |
| 1488 case KEYED_PROPERTY: | 1484 case KEYED_PROPERTY: |
| 1489 EmitKeyedPropertyLoad(property); | 1485 EmitKeyedPropertyLoad(property); |
| 1490 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | |
| 1491 break; | 1486 break; |
| 1492 } | 1487 } |
| 1493 } | 1488 } |
| 1494 | 1489 |
| 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 |
| 1495 Token::Value op = expr->binary_op(); | 1496 Token::Value op = expr->binary_op(); |
| 1496 __ push(rax); // Left operand goes on the stack. | 1497 __ push(rax); // Left operand goes on the stack. |
| 1497 VisitForAccumulatorValue(expr->value()); | 1498 VisitForAccumulatorValue(expr->value()); |
| 1498 | 1499 |
| 1499 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1500 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
| 1500 ? OVERWRITE_RIGHT | 1501 ? OVERWRITE_RIGHT |
| 1501 : NO_OVERWRITE; | 1502 : NO_OVERWRITE; |
| 1502 SetSourcePosition(expr->position() + 1); | 1503 SetSourcePosition(expr->position() + 1); |
| 1503 AccumulatorValueContext context(this); | 1504 AccumulatorValueContext context(this); |
| 1504 if (ShouldInlineSmiCase(op)) { | 1505 if (ShouldInlineSmiCase(op)) { |
| (...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2096 } | 2097 } |
| 2097 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 2098 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
| 2098 } else { | 2099 } else { |
| 2099 // Call to a keyed property. | 2100 // Call to a keyed property. |
| 2100 { PreservePositionScope scope(masm()->positions_recorder()); | 2101 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2101 VisitForStackValue(prop->obj()); | 2102 VisitForStackValue(prop->obj()); |
| 2102 } | 2103 } |
| 2103 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2104 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
| 2104 } | 2105 } |
| 2105 } else { | 2106 } 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 } |
| 2106 { PreservePositionScope scope(masm()->positions_recorder()); | 2116 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2107 VisitForStackValue(fun); | 2117 VisitForStackValue(fun); |
| 2108 } | 2118 } |
| 2109 // Load global receiver object. | 2119 // Load global receiver object. |
| 2110 __ movq(rbx, GlobalObjectOperand()); | 2120 __ movq(rbx, GlobalObjectOperand()); |
| 2111 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); | 2121 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); |
| 2112 // Emit function call. | 2122 // Emit function call. |
| 2113 EmitCallWithStub(expr); | 2123 EmitCallWithStub(expr); |
| 2114 } | 2124 } |
| 2115 | 2125 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2274 | 2284 |
| 2275 VisitForAccumulatorValue(args->at(0)); | 2285 VisitForAccumulatorValue(args->at(0)); |
| 2276 | 2286 |
| 2277 Label materialize_true, materialize_false; | 2287 Label materialize_true, materialize_false; |
| 2278 Label* if_true = NULL; | 2288 Label* if_true = NULL; |
| 2279 Label* if_false = NULL; | 2289 Label* if_false = NULL; |
| 2280 Label* fall_through = NULL; | 2290 Label* fall_through = NULL; |
| 2281 context()->PrepareTest(&materialize_true, &materialize_false, | 2291 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2282 &if_true, &if_false, &fall_through); | 2292 &if_true, &if_false, &fall_through); |
| 2283 | 2293 |
| 2284 if (FLAG_debug_code) __ AbortIfSmi(rax); | 2294 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only |
| 2285 | 2295 // used in a few functions in runtime.js which should not normally be hit by |
| 2286 // Check whether this map has already been checked to be safe for default | 2296 // this compiler. |
| 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 | |
| 2348 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2297 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 2298 __ jmp(if_false); |
| 2349 context()->Plug(if_true, if_false); | 2299 context()->Plug(if_true, if_false); |
| 2350 } | 2300 } |
| 2351 | 2301 |
| 2352 | 2302 |
| 2353 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { | 2303 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { |
| 2354 ASSERT(args->length() == 1); | 2304 ASSERT(args->length() == 1); |
| 2355 | 2305 |
| 2356 VisitForAccumulatorValue(args->at(0)); | 2306 VisitForAccumulatorValue(args->at(0)); |
| 2357 | 2307 |
| 2358 Label materialize_true, materialize_false; | 2308 Label materialize_true, materialize_false; |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2592 | 2542 |
| 2593 __ bind(&slow_allocate_heapnumber); | 2543 __ bind(&slow_allocate_heapnumber); |
| 2594 // Allocate a heap number. | 2544 // Allocate a heap number. |
| 2595 __ CallRuntime(Runtime::kNumberAlloc, 0); | 2545 __ CallRuntime(Runtime::kNumberAlloc, 0); |
| 2596 __ movq(rbx, rax); | 2546 __ movq(rbx, rax); |
| 2597 | 2547 |
| 2598 __ bind(&heapnumber_allocated); | 2548 __ bind(&heapnumber_allocated); |
| 2599 | 2549 |
| 2600 // Return a random uint32 number in rax. | 2550 // Return a random uint32 number in rax. |
| 2601 // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs. | 2551 // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs. |
| 2602 __ PrepareCallCFunction(1); | 2552 __ PrepareCallCFunction(0); |
| 2603 #ifdef _WIN64 | 2553 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 0); |
| 2604 __ LoadAddress(rcx, ExternalReference::isolate_address()); | |
| 2605 #else | |
| 2606 __ LoadAddress(rdi, ExternalReference::isolate_address()); | |
| 2607 #endif | |
| 2608 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); | |
| 2609 | 2554 |
| 2610 // Convert 32 random bits in rax to 0.(32 random bits) in a double | 2555 // Convert 32 random bits in rax to 0.(32 random bits) in a double |
| 2611 // by computing: | 2556 // by computing: |
| 2612 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | 2557 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). |
| 2613 __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. | 2558 __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. |
| 2614 __ movd(xmm1, rcx); | 2559 __ movd(xmm1, rcx); |
| 2615 __ movd(xmm0, rax); | 2560 __ movd(xmm0, rax); |
| 2616 __ cvtss2sd(xmm1, xmm1); | 2561 __ cvtss2sd(xmm1, xmm1); |
| 2617 __ xorpd(xmm0, xmm1); | 2562 __ xorpd(xmm0, xmm1); |
| 2618 __ subsd(xmm0, xmm1); | 2563 __ subsd(xmm0, xmm1); |
| (...skipping 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3643 VisitForStackValue(prop->obj()); | 3588 VisitForStackValue(prop->obj()); |
| 3644 VisitForAccumulatorValue(prop->key()); | 3589 VisitForAccumulatorValue(prop->key()); |
| 3645 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack | 3590 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack |
| 3646 __ push(rax); // Copy of key, needed for later store. | 3591 __ push(rax); // Copy of key, needed for later store. |
| 3647 EmitKeyedPropertyLoad(prop); | 3592 EmitKeyedPropertyLoad(prop); |
| 3648 } | 3593 } |
| 3649 } | 3594 } |
| 3650 | 3595 |
| 3651 // We need a second deoptimization point after loading the value | 3596 // We need a second deoptimization point after loading the value |
| 3652 // in case evaluating the property load my have a side effect. | 3597 // in case evaluating the property load my have a side effect. |
| 3653 if (assign_type == VARIABLE) { | 3598 PrepareForBailout(expr->increment(), TOS_REG); |
| 3654 PrepareForBailout(expr->expression(), TOS_REG); | |
| 3655 } else { | |
| 3656 PrepareForBailout(expr->increment(), TOS_REG); | |
| 3657 } | |
| 3658 | 3599 |
| 3659 // Call ToNumber only if operand is not a smi. | 3600 // Call ToNumber only if operand is not a smi. |
| 3660 NearLabel no_conversion; | 3601 NearLabel no_conversion; |
| 3661 Condition is_smi; | 3602 Condition is_smi; |
| 3662 is_smi = masm_->CheckSmi(rax); | 3603 is_smi = masm_->CheckSmi(rax); |
| 3663 __ j(is_smi, &no_conversion); | 3604 __ j(is_smi, &no_conversion); |
| 3664 ToNumberStub convert_stub; | 3605 ToNumberStub convert_stub; |
| 3665 __ CallStub(&convert_stub); | 3606 __ CallStub(&convert_stub); |
| 3666 __ bind(&no_conversion); | 3607 __ bind(&no_conversion); |
| 3667 | 3608 |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4172 __ ret(0); | 4113 __ ret(0); |
| 4173 } | 4114 } |
| 4174 | 4115 |
| 4175 | 4116 |
| 4176 #undef __ | 4117 #undef __ |
| 4177 | 4118 |
| 4178 | 4119 |
| 4179 } } // namespace v8::internal | 4120 } } // namespace v8::internal |
| 4180 | 4121 |
| 4181 #endif // V8_TARGET_ARCH_X64 | 4122 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |