Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 2303) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -2329,9 +2329,6 @@ |
frame_->SetElementAt(0, &result); |
} else if (var != NULL && var->slot() != NULL && |
var->slot()->type() == Slot::LOOKUP) { |
- // TODO(X64): Enable calls of non-global functions. |
- UNIMPLEMENTED(); |
- /* |
// ---------------------------------- |
// JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj |
// ---------------------------------- |
@@ -2339,8 +2336,8 @@ |
// Load the function from the context. Sync the frame so we can |
// push the arguments directly into place. |
frame_->SyncRange(0, frame_->element_count() - 1); |
- frame_->EmitPush(esi); |
- frame_->EmitPush(Immediate(var->name())); |
+ frame_->EmitPush(rsi); |
+ frame_->EmitPush(var->name()); |
frame_->CallRuntime(Runtime::kLoadContextSlot, 2); |
// The runtime call returns a pair of values in rax and rdx. The |
// looked-up function is in rax and the receiver is in rdx. These |
@@ -2356,7 +2353,6 @@ |
// Call the function. |
CallWithArguments(args, node->position()); |
- */ |
} else if (property != NULL) { |
// Check if the key is a literal string. |
Literal* literal = property->key()->AsLiteral(); |
@@ -3946,8 +3942,72 @@ |
Slot* slot, |
TypeofState typeof_state, |
JumpTarget* slow) { |
- UNIMPLEMENTED(); |
- return Result(rax); |
+ // Check that no extension objects have been created by calls to |
+ // eval from the current scope to the global scope. |
+ Register context = rsi; |
+ Result tmp = allocator_->Allocate(); |
+ ASSERT(tmp.is_valid()); // All non-reserved registers were available. |
+ |
+ Scope* s = scope(); |
+ while (s != NULL) { |
+ if (s->num_heap_slots() > 0) { |
+ if (s->calls_eval()) { |
+ // Check that extension is NULL. |
+ __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), |
+ Immediate(0)); |
+ slow->Branch(not_equal, not_taken); |
+ } |
+ // Load next context in chain. |
+ __ movq(tmp.reg(), ContextOperand(context, Context::CLOSURE_INDEX)); |
+ __ movq(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset)); |
+ context = tmp.reg(); |
+ } |
+ // If no outer scope calls eval, we do not need to check more |
+ // context extensions. If we have reached an eval scope, we check |
+ // all extensions from this point. |
+ if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; |
+ s = s->outer_scope(); |
+ } |
+ |
+ if (s->is_eval_scope()) { |
+ // Loop up the context chain. There is no frame effect so it is |
+ // safe to use raw labels here. |
+ Label next, fast; |
+ if (!context.is(tmp.reg())) { |
+ __ movq(tmp.reg(), context); |
+ } |
+ // Load map for comparison into register, outside loop. |
+ __ Move(kScratchRegister, Factory::global_context_map()); |
+ __ bind(&next); |
+ // Terminate at global context. |
+ __ cmpq(kScratchRegister, FieldOperand(tmp.reg(), HeapObject::kMapOffset)); |
+ __ j(equal, &fast); |
+ // Check that extension is NULL. |
+ __ cmpq(ContextOperand(tmp.reg(), Context::EXTENSION_INDEX), Immediate(0)); |
+ slow->Branch(not_equal); |
+ // Load next context in chain. |
+ __ movq(tmp.reg(), ContextOperand(tmp.reg(), Context::CLOSURE_INDEX)); |
+ __ movq(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset)); |
+ __ jmp(&next); |
+ __ bind(&fast); |
+ } |
+ tmp.Unuse(); |
+ |
+ // All extension objects were empty and it is safe to use a global |
+ // load IC call. |
+ LoadGlobal(); |
+ frame_->Push(slot->var()->name()); |
+ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
+ ? RelocInfo::CODE_TARGET |
+ : RelocInfo::CODE_TARGET_CONTEXT; |
+ Result answer = frame_->CallLoadIC(mode); |
+ // A test rax instruction following the call signals that the inobject |
+ // property case was inlined. Ensure that there is not a test eax |
+ // instruction here. |
+ __ nop(); |
+ // Discard the global object. The result is in answer. |
+ frame_->Drop(); |
+ return answer; |
} |
@@ -5385,12 +5445,41 @@ |
} |
+// End of CodeGenerator implementation. |
+void UnarySubStub::Generate(MacroAssembler* masm) { |
+ Label slow; |
+ Label done; |
+ Label try_float; |
-// End of CodeGenerator implementation. |
+ // Check whether the value is a smi. |
+ __ testl(rax, Immediate(kSmiTagMask)); |
+ // TODO(X64): Add inline code that handles floats, as on ia32 platform. |
+ __ j(not_zero, &slow); |
-void UnarySubStub::Generate(MacroAssembler* masm) { |
- UNIMPLEMENTED(); |
+ // Enter runtime system if the value of the expression is zero |
+ // to make sure that we switch between 0 and -0. |
+ __ testq(rax, rax); |
+ __ j(zero, &slow); |
+ |
+ // The value of the expression is a smi that is not zero. Try |
+ // optimistic subtraction '0 - value'. |
+ __ movq(rdx, rax); |
+ __ xor_(rax, rax); |
+ __ subl(rax, rdx); |
+ __ j(no_overflow, &done); |
+ // Restore rax and enter runtime system. |
+ __ movq(rax, rdx); |
+ |
+ // Enter runtime system. |
+ __ bind(&slow); |
+ __ pop(rcx); // pop return address |
+ __ push(rax); |
+ __ push(rcx); // push return address |
+ __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); |
+ |
+ __ bind(&done); |
+ __ StubReturn(1); |
} |