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 2178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2189 #ifdef ENABLE_DEBUGGER_SUPPORT | 2189 #ifdef ENABLE_DEBUGGER_SUPPORT |
2190 // Spill everything, even constants, to the frame. | 2190 // Spill everything, even constants, to the frame. |
2191 frame_->SpillAll(); | 2191 frame_->SpillAll(); |
2192 frame_->CallRuntime(Runtime::kDebugBreak, 0); | 2192 frame_->CallRuntime(Runtime::kDebugBreak, 0); |
2193 // Ignore the return value. | 2193 // Ignore the return value. |
2194 #endif | 2194 #endif |
2195 } | 2195 } |
2196 | 2196 |
2197 | 2197 |
2198 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { | 2198 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { |
2199 // Call the runtime to instantiate the function boilerplate object. | 2199 ASSERT(boilerplate->IsBoilerplate()); |
| 2200 |
2200 // The inevitable call will sync frame elements to memory anyway, so | 2201 // The inevitable call will sync frame elements to memory anyway, so |
2201 // we do it eagerly to allow us to push the arguments directly into | 2202 // we do it eagerly to allow us to push the arguments directly into |
2202 // place. | 2203 // place. |
2203 ASSERT(boilerplate->IsBoilerplate()); | |
2204 frame_->SyncRange(0, frame_->element_count() - 1); | 2204 frame_->SyncRange(0, frame_->element_count() - 1); |
2205 | 2205 |
2206 // Create a new closure. | 2206 // Use the fast case closure allocation code that allocates in new |
2207 frame_->EmitPush(rsi); | 2207 // space for nested functions that don't need literals cloning. |
2208 __ movq(kScratchRegister, boilerplate, RelocInfo::EMBEDDED_OBJECT); | 2208 if (scope()->is_function_scope() && boilerplate->NumberOfLiterals() == 0) { |
2209 frame_->EmitPush(kScratchRegister); | 2209 FastNewClosureStub stub; |
2210 Result result = frame_->CallRuntime(Runtime::kNewClosure, 2); | 2210 frame_->Push(boilerplate); |
2211 frame_->Push(&result); | 2211 Result answer = frame_->CallStub(&stub, 1); |
| 2212 frame_->Push(&answer); |
| 2213 } else { |
| 2214 // Call the runtime to instantiate the function boilerplate |
| 2215 // object. |
| 2216 frame_->EmitPush(rsi); |
| 2217 frame_->EmitPush(boilerplate); |
| 2218 Result result = frame_->CallRuntime(Runtime::kNewClosure, 2); |
| 2219 frame_->Push(&result); |
| 2220 } |
2212 } | 2221 } |
2213 | 2222 |
2214 | 2223 |
2215 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { | 2224 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { |
2216 Comment cmnt(masm_, "[ FunctionLiteral"); | 2225 Comment cmnt(masm_, "[ FunctionLiteral"); |
2217 | 2226 |
2218 // Build the function boilerplate and instantiate it. | 2227 // Build the function boilerplate and instantiate it. |
2219 Handle<JSFunction> boilerplate = | 2228 Handle<JSFunction> boilerplate = |
2220 Compiler::BuildBoilerplate(node, script_, this); | 2229 Compiler::BuildBoilerplate(node, script_, this); |
2221 // Check for stack-overflow exception. | 2230 // Check for stack-overflow exception. |
(...skipping 3837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6059 } | 6068 } |
6060 break; | 6069 break; |
6061 } | 6070 } |
6062 | 6071 |
6063 default: | 6072 default: |
6064 UNREACHABLE(); | 6073 UNREACHABLE(); |
6065 } | 6074 } |
6066 } | 6075 } |
6067 | 6076 |
6068 | 6077 |
| 6078 void FastNewClosureStub::Generate(MacroAssembler* masm) { |
| 6079 // Clone the boilerplate in new space. Set the context to the |
| 6080 // current context in rsi. |
| 6081 Label gc; |
| 6082 __ AllocateInNewSpace(JSFunction::kSize, rax, rbx, rcx, &gc, TAG_OBJECT); |
| 6083 |
| 6084 // Get the boilerplate function from the stack. |
| 6085 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); |
| 6086 |
| 6087 // Compute the function map in the current global context and set that |
| 6088 // as the map of the allocated object. |
| 6089 __ movq(rcx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 6090 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset)); |
| 6091 __ movq(rcx, Operand(rcx, Context::SlotOffset(Context::FUNCTION_MAP_INDEX))); |
| 6092 __ movq(FieldOperand(rax, JSObject::kMapOffset), rcx); |
| 6093 |
| 6094 // Clone the rest of the boilerplate fields. We don't have to update |
| 6095 // the write barrier because the allocated object is in new space. |
| 6096 for (int offset = kPointerSize; |
| 6097 offset < JSFunction::kSize; |
| 6098 offset += kPointerSize) { |
| 6099 if (offset == JSFunction::kContextOffset) { |
| 6100 __ movq(FieldOperand(rax, offset), rsi); |
| 6101 } else { |
| 6102 __ movq(rbx, FieldOperand(rdx, offset)); |
| 6103 __ movq(FieldOperand(rax, offset), rbx); |
| 6104 } |
| 6105 } |
| 6106 |
| 6107 // Return and remove the on-stack parameter. |
| 6108 __ ret(1 * kPointerSize); |
| 6109 |
| 6110 // Create a new closure through the slower runtime call. |
| 6111 __ bind(&gc); |
| 6112 __ pop(rcx); // Temporarily remove return address. |
| 6113 __ pop(rdx); |
| 6114 __ push(rsi); |
| 6115 __ push(rdx); |
| 6116 __ push(rcx); // Restore return address. |
| 6117 __ TailCallRuntime(ExternalReference(Runtime::kNewClosure), 2, 1); |
| 6118 } |
| 6119 |
| 6120 |
6069 void ToBooleanStub::Generate(MacroAssembler* masm) { | 6121 void ToBooleanStub::Generate(MacroAssembler* masm) { |
6070 Label false_result, true_result, not_string; | 6122 Label false_result, true_result, not_string; |
6071 __ movq(rax, Operand(rsp, 1 * kPointerSize)); | 6123 __ movq(rax, Operand(rsp, 1 * kPointerSize)); |
6072 | 6124 |
6073 // 'null' => false. | 6125 // 'null' => false. |
6074 __ CompareRoot(rax, Heap::kNullValueRootIndex); | 6126 __ CompareRoot(rax, Heap::kNullValueRootIndex); |
6075 __ j(equal, &false_result); | 6127 __ j(equal, &false_result); |
6076 | 6128 |
6077 // Get the map and type of the heap object. | 6129 // Get the map and type of the heap object. |
6078 // We don't use CmpObjectType because we manipulate the type field. | 6130 // We don't use CmpObjectType because we manipulate the type field. |
(...skipping 2044 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8123 masm.GetCode(&desc); | 8175 masm.GetCode(&desc); |
8124 // Call the function from C++. | 8176 // Call the function from C++. |
8125 return FUNCTION_CAST<ModuloFunction>(buffer); | 8177 return FUNCTION_CAST<ModuloFunction>(buffer); |
8126 } | 8178 } |
8127 | 8179 |
8128 #endif | 8180 #endif |
8129 | 8181 |
8130 #undef __ | 8182 #undef __ |
8131 | 8183 |
8132 } } // namespace v8::internal | 8184 } } // namespace v8::internal |
OLD | NEW |