Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 2254) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -123,10 +123,21 @@ |
} |
-void CodeGenerator::DeclareGlobals(Handle<FixedArray> a) { |
- UNIMPLEMENTED(); |
+void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
+ // Call the runtime to declare the globals. The inevitable call |
+ // will sync frame elements to memory anyway, so we do it eagerly to |
+ // allow us to push the arguments directly into place. |
+ frame_->SyncRange(0, frame_->element_count() - 1); |
+ |
+ __ movq(kScratchRegister, pairs, RelocInfo::EMBEDDED_OBJECT); |
+ frame_->EmitPush(kScratchRegister); |
+ frame_->EmitPush(rsi); // The context is the second argument. |
+ frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); |
+ Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); |
+ // Return value is ignored. |
} |
+ |
void CodeGenerator::TestCodeGenerator() { |
// Compile a function from a string, and run it. |
@@ -286,10 +297,35 @@ |
// Ignore the return value. |
} |
#endif |
+ VisitStatements(body); |
+ |
+ // Handle the return from the function. |
+ if (has_valid_frame()) { |
+ // If there is a valid frame, control flow can fall off the end of |
+ // the body. In that case there is an implicit return statement. |
+ ASSERT(!function_return_is_shadowed_); |
+ CodeForReturnPosition(function); |
+ frame_->PrepareForReturn(); |
+ Result undefined(Factory::undefined_value()); |
+ if (function_return_.is_bound()) { |
+ function_return_.Jump(&undefined); |
+ } else { |
+ function_return_.Bind(&undefined); |
+ GenerateReturnSequence(&undefined); |
+ } |
+ } else if (function_return_.is_linked()) { |
+ // If the return target has dangling jumps to it, then we have not |
+ // yet generated the return sequence. This can happen when (a) |
+ // control does not flow off the end of the body so we did not |
+ // compile an artificial return statement just above, and (b) there |
+ // are return statements in the body but (c) they are all shadowed. |
+ Result return_value; |
+ function_return_.Bind(&return_value); |
+ GenerateReturnSequence(&return_value); |
+ } |
} |
+ } |
- VisitStatements(body); |
- } |
// Adjust for function-level loop nesting. |
loop_nesting_ -= function->loop_nesting(); |
@@ -1319,13 +1355,77 @@ |
} |
-void CodeGenerator::VisitCallNew(CallNew* a) { |
- UNIMPLEMENTED(); |
+void CodeGenerator::VisitCallNew(CallNew* node) { |
+ Comment cmnt(masm_, "[ CallNew"); |
+ CodeForStatementPosition(node); |
+ |
+ // According to ECMA-262, section 11.2.2, page 44, the function |
+ // expression in new calls must be evaluated before the |
+ // arguments. This is different from ordinary calls, where the |
+ // actual function to call is resolved after the arguments have been |
+ // evaluated. |
+ |
+ // Compute function to call and use the global object as the |
+ // receiver. There is no need to use the global proxy here because |
+ // it will always be replaced with a newly allocated object. |
+ Load(node->expression()); |
+ LoadGlobal(); |
+ |
+ // Push the arguments ("left-to-right") on the stack. |
+ ZoneList<Expression*>* args = node->arguments(); |
+ int arg_count = args->length(); |
+ for (int i = 0; i < arg_count; i++) { |
+ Load(args->at(i)); |
+ } |
+ |
+ // Call the construct call builtin that handles allocation and |
+ // constructor invocation. |
+ CodeForSourcePosition(node->position()); |
+ Result result = frame_->CallConstructor(arg_count); |
+ // Replace the function on the stack with the result. |
+ frame_->SetElementAt(0, &result); |
} |
-void CodeGenerator::VisitCallRuntime(CallRuntime* a) { |
- UNIMPLEMENTED(); |
+void CodeGenerator::VisitCallRuntime(CallRuntime* node) { |
+ if (CheckForInlineRuntimeCall(node)) { |
+ return; |
+ } |
+ |
+ ZoneList<Expression*>* args = node->arguments(); |
+ Comment cmnt(masm_, "[ CallRuntime"); |
+ Runtime::Function* function = node->function(); |
+ |
+ if (function == NULL) { |
+ // Prepare stack for calling JS runtime function. |
+ frame_->Push(node->name()); |
+ // Push the builtins object found in the current global object. |
+ Result temp = allocator()->Allocate(); |
William Hesse
2009/06/24 07:55:57
Use kScratchRegister here.
Mads Ager (chromium)
2009/06/24 08:18:50
Done.
|
+ ASSERT(temp.is_valid()); |
+ __ movq(temp.reg(), GlobalObject()); |
+ __ movq(temp.reg(), |
+ FieldOperand(temp.reg(), GlobalObject::kBuiltinsOffset)); |
+ frame_->Push(&temp); |
+ } |
+ |
+ // Push the arguments ("left-to-right"). |
+ int arg_count = args->length(); |
+ for (int i = 0; i < arg_count; i++) { |
+ Load(args->at(i)); |
+ } |
+ |
+ if (function == NULL) { |
+ // Call the JS runtime function. |
+ Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET, |
+ arg_count, |
+ loop_nesting_); |
+ frame_->RestoreContextRegister(); |
+ frame_->SetElementAt(0, &answer); |
+ } else { |
+ // Call the C runtime function. |
+ Result answer = frame_->CallRuntime(function, arg_count); |
+ frame_->Push(&answer); |
+ } |
} |
@@ -1345,10 +1445,12 @@ |
UNIMPLEMENTED(); |
} |
-void CodeGenerator::VisitThisFunction(ThisFunction* a) { |
- UNIMPLEMENTED(); |
+ |
+void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
+ frame_->PushFunction(); |
} |
+ |
void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { |
UNIMPLEMENTED(); |
} |
@@ -1542,7 +1644,7 @@ |
ASSERT(kSmiTag == 0); |
__ testq(value.reg(), value.reg()); |
dest->false_target()->Branch(zero); |
- __ testq(value.reg(), Immediate(kSmiTagMask)); |
+ __ testl(value.reg(), Immediate(kSmiTagMask)); |
William Hesse
2009/06/24 07:55:57
We have many of these throughout the code, and hav
Mads Ager (chromium)
2009/06/24 08:18:50
We were using it inconsistently before. There was
|
dest->true_target()->Branch(zero); |
// Call the stub for all other cases. |
@@ -2056,7 +2158,7 @@ |
GetName()); |
// Check that the receiver is a heap object. |
- __ testq(receiver.reg(), Immediate(kSmiTagMask)); |
+ __ testl(receiver.reg(), Immediate(kSmiTagMask)); |
deferred->Branch(zero); |
__ bind(deferred->patch_site()); |
@@ -2370,8 +2472,8 @@ |
// Check for negative zero result. |
__ NegativeZeroTest(rax, rcx, slow); // use ecx = x | y |
// Tag the result and store it in register rax. |
- ASSERT(kSmiTagSize == kTimes2); // adjust code if not the case |
- __ lea(rax, Operand(rax, rax, kTimes1, kSmiTag)); |
+ ASSERT(kSmiTagSize == times_2); // adjust code if not the case |
+ __ lea(rax, Operand(rax, rax, times_1, kSmiTag)); |
break; |
case Token::MOD: |
@@ -2435,8 +2537,8 @@ |
UNREACHABLE(); |
} |
// Tag the result and store it in register eax. |
- ASSERT(kSmiTagSize == kTimes2); // adjust code if not the case |
- __ lea(rax, Operand(rax, rax, kTimes1, kSmiTag)); |
+ ASSERT(kSmiTagSize == times_2); // adjust code if not the case |
+ __ lea(rax, Operand(rax, rax, times_1, kSmiTag)); |
break; |
default: |
@@ -2518,7 +2620,7 @@ |
__ movq(rdi, Operand(rsp, (argc_ + 2) * kPointerSize)); |
// Check that the function really is a JavaScript function. |
- __ testq(rdi, Immediate(kSmiTagMask)); |
+ __ testl(rdi, Immediate(kSmiTagMask)); |
__ j(zero, &slow); |
// Goto slow case if we do not have a function. |
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
@@ -2583,7 +2685,7 @@ |
// Patch the arguments.length and the parameters pointer. |
__ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
__ movq(Operand(rsp, 1 * kPointerSize), rcx); |
- __ lea(rdx, Operand(rdx, rcx, kTimes4, kDisplacement)); |
+ __ lea(rdx, Operand(rdx, rcx, times_4, kDisplacement)); |
__ movq(Operand(rsp, 2 * kPointerSize), rdx); |
// Do the runtime call to allocate the arguments object. |
@@ -2621,9 +2723,9 @@ |
// Shifting code depends on SmiEncoding being equivalent to left shift: |
// we multiply by four to get pointer alignment. |
ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
- __ lea(rbx, Operand(rbp, rax, kTimes4, 0)); |
+ __ lea(rbx, Operand(rbp, rax, times_4, 0)); |
__ neg(rdx); |
- __ movq(rax, Operand(rbx, rdx, kTimes4, kDisplacement)); |
+ __ movq(rax, Operand(rbx, rdx, times_4, kDisplacement)); |
__ Ret(); |
// Arguments adaptor case: Check index against actual arguments |
@@ -2638,9 +2740,9 @@ |
// Shifting code depends on SmiEncoding being equivalent to left shift: |
// we multiply by four to get pointer alignment. |
ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
- __ lea(rbx, Operand(rbx, rcx, kTimes4, 0)); |
+ __ lea(rbx, Operand(rbx, rcx, times_4, 0)); |
__ neg(rdx); |
- __ movq(rax, Operand(rbx, rdx, kTimes4, kDisplacement)); |
+ __ movq(rax, Operand(rbx, rdx, times_4, kDisplacement)); |
__ Ret(); |
// Slow-case: Handle non-smi or out-of-bounds access to arguments |