OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 2311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2322 // Call the IC initialization code. | 2322 // Call the IC initialization code. |
2323 CodeForSourcePosition(node->position()); | 2323 CodeForSourcePosition(node->position()); |
2324 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, | 2324 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, |
2325 arg_count, | 2325 arg_count, |
2326 loop_nesting()); | 2326 loop_nesting()); |
2327 frame_->RestoreContextRegister(); | 2327 frame_->RestoreContextRegister(); |
2328 // Replace the function on the stack with the result. | 2328 // Replace the function on the stack with the result. |
2329 frame_->SetElementAt(0, &result); | 2329 frame_->SetElementAt(0, &result); |
2330 } else if (var != NULL && var->slot() != NULL && | 2330 } else if (var != NULL && var->slot() != NULL && |
2331 var->slot()->type() == Slot::LOOKUP) { | 2331 var->slot()->type() == Slot::LOOKUP) { |
2332 // TODO(X64): Enable calls of non-global functions. | |
2333 UNIMPLEMENTED(); | |
2334 /* | |
2335 // ---------------------------------- | 2332 // ---------------------------------- |
2336 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj | 2333 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj |
2337 // ---------------------------------- | 2334 // ---------------------------------- |
2338 | 2335 |
2339 // Load the function from the context. Sync the frame so we can | 2336 // Load the function from the context. Sync the frame so we can |
2340 // push the arguments directly into place. | 2337 // push the arguments directly into place. |
2341 frame_->SyncRange(0, frame_->element_count() - 1); | 2338 frame_->SyncRange(0, frame_->element_count() - 1); |
2342 frame_->EmitPush(esi); | 2339 frame_->EmitPush(rsi); |
2343 frame_->EmitPush(Immediate(var->name())); | 2340 frame_->EmitPush(var->name()); |
2344 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); | 2341 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); |
2345 // The runtime call returns a pair of values in rax and rdx. The | 2342 // The runtime call returns a pair of values in rax and rdx. The |
2346 // looked-up function is in rax and the receiver is in rdx. These | 2343 // looked-up function is in rax and the receiver is in rdx. These |
2347 // register references are not ref counted here. We spill them | 2344 // register references are not ref counted here. We spill them |
2348 // eagerly since they are arguments to an inevitable call (and are | 2345 // eagerly since they are arguments to an inevitable call (and are |
2349 // not sharable by the arguments). | 2346 // not sharable by the arguments). |
2350 ASSERT(!allocator()->is_used(rax)); | 2347 ASSERT(!allocator()->is_used(rax)); |
2351 frame_->EmitPush(rax); | 2348 frame_->EmitPush(rax); |
2352 | 2349 |
2353 // Load the receiver. | 2350 // Load the receiver. |
2354 ASSERT(!allocator()->is_used(rdx)); | 2351 ASSERT(!allocator()->is_used(rdx)); |
2355 frame_->EmitPush(rdx); | 2352 frame_->EmitPush(rdx); |
2356 | 2353 |
2357 // Call the function. | 2354 // Call the function. |
2358 CallWithArguments(args, node->position()); | 2355 CallWithArguments(args, node->position()); |
2359 */ | |
2360 } else if (property != NULL) { | 2356 } else if (property != NULL) { |
2361 // Check if the key is a literal string. | 2357 // Check if the key is a literal string. |
2362 Literal* literal = property->key()->AsLiteral(); | 2358 Literal* literal = property->key()->AsLiteral(); |
2363 | 2359 |
2364 if (literal != NULL && literal->handle()->IsSymbol()) { | 2360 if (literal != NULL && literal->handle()->IsSymbol()) { |
2365 // ------------------------------------------------------------------ | 2361 // ------------------------------------------------------------------ |
2366 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' | 2362 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' |
2367 // ------------------------------------------------------------------ | 2363 // ------------------------------------------------------------------ |
2368 | 2364 |
2369 // TODO(X64): Consider optimizing Function.prototype.apply calls | 2365 // TODO(X64): Consider optimizing Function.prototype.apply calls |
(...skipping 1569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3939 | 3935 |
3940 exit.Bind(); | 3936 exit.Bind(); |
3941 } | 3937 } |
3942 } | 3938 } |
3943 | 3939 |
3944 | 3940 |
3945 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( | 3941 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( |
3946 Slot* slot, | 3942 Slot* slot, |
3947 TypeofState typeof_state, | 3943 TypeofState typeof_state, |
3948 JumpTarget* slow) { | 3944 JumpTarget* slow) { |
3949 UNIMPLEMENTED(); | 3945 // Check that no extension objects have been created by calls to |
3950 return Result(rax); | 3946 // eval from the current scope to the global scope. |
| 3947 Register context = rsi; |
| 3948 Result tmp = allocator_->Allocate(); |
| 3949 ASSERT(tmp.is_valid()); // All non-reserved registers were available. |
| 3950 |
| 3951 Scope* s = scope(); |
| 3952 while (s != NULL) { |
| 3953 if (s->num_heap_slots() > 0) { |
| 3954 if (s->calls_eval()) { |
| 3955 // Check that extension is NULL. |
| 3956 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), |
| 3957 Immediate(0)); |
| 3958 slow->Branch(not_equal, not_taken); |
| 3959 } |
| 3960 // Load next context in chain. |
| 3961 __ movq(tmp.reg(), ContextOperand(context, Context::CLOSURE_INDEX)); |
| 3962 __ movq(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset)); |
| 3963 context = tmp.reg(); |
| 3964 } |
| 3965 // If no outer scope calls eval, we do not need to check more |
| 3966 // context extensions. If we have reached an eval scope, we check |
| 3967 // all extensions from this point. |
| 3968 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; |
| 3969 s = s->outer_scope(); |
| 3970 } |
| 3971 |
| 3972 if (s->is_eval_scope()) { |
| 3973 // Loop up the context chain. There is no frame effect so it is |
| 3974 // safe to use raw labels here. |
| 3975 Label next, fast; |
| 3976 if (!context.is(tmp.reg())) { |
| 3977 __ movq(tmp.reg(), context); |
| 3978 } |
| 3979 // Load map for comparison into register, outside loop. |
| 3980 __ Move(kScratchRegister, Factory::global_context_map()); |
| 3981 __ bind(&next); |
| 3982 // Terminate at global context. |
| 3983 __ cmpq(kScratchRegister, FieldOperand(tmp.reg(), HeapObject::kMapOffset)); |
| 3984 __ j(equal, &fast); |
| 3985 // Check that extension is NULL. |
| 3986 __ cmpq(ContextOperand(tmp.reg(), Context::EXTENSION_INDEX), Immediate(0)); |
| 3987 slow->Branch(not_equal); |
| 3988 // Load next context in chain. |
| 3989 __ movq(tmp.reg(), ContextOperand(tmp.reg(), Context::CLOSURE_INDEX)); |
| 3990 __ movq(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset)); |
| 3991 __ jmp(&next); |
| 3992 __ bind(&fast); |
| 3993 } |
| 3994 tmp.Unuse(); |
| 3995 |
| 3996 // All extension objects were empty and it is safe to use a global |
| 3997 // load IC call. |
| 3998 LoadGlobal(); |
| 3999 frame_->Push(slot->var()->name()); |
| 4000 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
| 4001 ? RelocInfo::CODE_TARGET |
| 4002 : RelocInfo::CODE_TARGET_CONTEXT; |
| 4003 Result answer = frame_->CallLoadIC(mode); |
| 4004 // A test rax instruction following the call signals that the inobject |
| 4005 // property case was inlined. Ensure that there is not a test eax |
| 4006 // instruction here. |
| 4007 __ nop(); |
| 4008 // Discard the global object. The result is in answer. |
| 4009 frame_->Drop(); |
| 4010 return answer; |
3951 } | 4011 } |
3952 | 4012 |
3953 | 4013 |
3954 void CodeGenerator::LoadGlobal() { | 4014 void CodeGenerator::LoadGlobal() { |
3955 if (in_spilled_code()) { | 4015 if (in_spilled_code()) { |
3956 frame_->EmitPush(GlobalObject()); | 4016 frame_->EmitPush(GlobalObject()); |
3957 } else { | 4017 } else { |
3958 Result temp = allocator_->Allocate(); | 4018 Result temp = allocator_->Allocate(); |
3959 __ movq(temp.reg(), GlobalObject()); | 4019 __ movq(temp.reg(), GlobalObject()); |
3960 frame_->Push(&temp); | 4020 frame_->Push(&temp); |
(...skipping 1417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5378 break; | 5438 break; |
5379 } | 5439 } |
5380 if (answer_object == Heap::undefined_value()) { | 5440 if (answer_object == Heap::undefined_value()) { |
5381 return false; | 5441 return false; |
5382 } | 5442 } |
5383 frame_->Push(Handle<Object>(answer_object)); | 5443 frame_->Push(Handle<Object>(answer_object)); |
5384 return true; | 5444 return true; |
5385 } | 5445 } |
5386 | 5446 |
5387 | 5447 |
5388 | |
5389 | |
5390 // End of CodeGenerator implementation. | 5448 // End of CodeGenerator implementation. |
5391 | 5449 |
5392 void UnarySubStub::Generate(MacroAssembler* masm) { | 5450 void UnarySubStub::Generate(MacroAssembler* masm) { |
5393 UNIMPLEMENTED(); | 5451 Label slow; |
| 5452 Label done; |
| 5453 Label try_float; |
| 5454 |
| 5455 // Check whether the value is a smi. |
| 5456 __ testl(rax, Immediate(kSmiTagMask)); |
| 5457 // TODO(X64): Add inline code that handles floats, as on ia32 platform. |
| 5458 __ j(not_zero, &slow); |
| 5459 |
| 5460 // Enter runtime system if the value of the expression is zero |
| 5461 // to make sure that we switch between 0 and -0. |
| 5462 __ testq(rax, rax); |
| 5463 __ j(zero, &slow); |
| 5464 |
| 5465 // The value of the expression is a smi that is not zero. Try |
| 5466 // optimistic subtraction '0 - value'. |
| 5467 __ movq(rdx, rax); |
| 5468 __ xor_(rax, rax); |
| 5469 __ subl(rax, rdx); |
| 5470 __ j(no_overflow, &done); |
| 5471 // Restore rax and enter runtime system. |
| 5472 __ movq(rax, rdx); |
| 5473 |
| 5474 // Enter runtime system. |
| 5475 __ bind(&slow); |
| 5476 __ pop(rcx); // pop return address |
| 5477 __ push(rax); |
| 5478 __ push(rcx); // push return address |
| 5479 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); |
| 5480 |
| 5481 __ bind(&done); |
| 5482 __ StubReturn(1); |
5394 } | 5483 } |
5395 | 5484 |
5396 | 5485 |
5397 void CompareStub::Generate(MacroAssembler* masm) { | 5486 void CompareStub::Generate(MacroAssembler* masm) { |
5398 Label call_builtin, done; | 5487 Label call_builtin, done; |
5399 | 5488 |
5400 // NOTICE! This code is only reached after a smi-fast-case check, so | 5489 // NOTICE! This code is only reached after a smi-fast-case check, so |
5401 // it is certain that at least one operand isn't a smi. | 5490 // it is certain that at least one operand isn't a smi. |
5402 | 5491 |
5403 if (cc_ == equal) { // Both strict and non-strict. | 5492 if (cc_ == equal) { // Both strict and non-strict. |
(...skipping 1296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6700 int CompareStub::MinorKey() { | 6789 int CompareStub::MinorKey() { |
6701 // Encode the two parameters in a unique 16 bit value. | 6790 // Encode the two parameters in a unique 16 bit value. |
6702 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); | 6791 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); |
6703 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); | 6792 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); |
6704 } | 6793 } |
6705 | 6794 |
6706 | 6795 |
6707 #undef __ | 6796 #undef __ |
6708 | 6797 |
6709 } } // namespace v8::internal | 6798 } } // namespace v8::internal |
OLD | NEW |