| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 2211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2222 #ifdef ENABLE_DEBUGGER_SUPPORT | 2222 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 2223 // Spill everything, even constants, to the frame. | 2223 // Spill everything, even constants, to the frame. |
| 2224 frame_->SpillAll(); | 2224 frame_->SpillAll(); |
| 2225 | 2225 |
| 2226 frame_->DebugBreak(); | 2226 frame_->DebugBreak(); |
| 2227 // Ignore the return value. | 2227 // Ignore the return value. |
| 2228 #endif | 2228 #endif |
| 2229 } | 2229 } |
| 2230 | 2230 |
| 2231 | 2231 |
| 2232 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { | 2232 void CodeGenerator::InstantiateFunction( |
| 2233 ASSERT(boilerplate->IsBoilerplate()); | 2233 Handle<SharedFunctionInfo> function_info) { |
| 2234 | |
| 2235 // The inevitable call will sync frame elements to memory anyway, so | 2234 // The inevitable call will sync frame elements to memory anyway, so |
| 2236 // we do it eagerly to allow us to push the arguments directly into | 2235 // we do it eagerly to allow us to push the arguments directly into |
| 2237 // place. | 2236 // place. |
| 2238 frame_->SyncRange(0, frame_->element_count() - 1); | 2237 frame_->SyncRange(0, frame_->element_count() - 1); |
| 2239 | 2238 |
| 2240 // Use the fast case closure allocation code that allocates in new | 2239 // Use the fast case closure allocation code that allocates in new |
| 2241 // space for nested functions that don't need literals cloning. | 2240 // space for nested functions that don't need literals cloning. |
| 2242 if (scope()->is_function_scope() && boilerplate->NumberOfLiterals() == 0) { | 2241 if (scope()->is_function_scope() && function_info->num_literals() == 0) { |
| 2243 FastNewClosureStub stub; | 2242 FastNewClosureStub stub; |
| 2244 frame_->Push(boilerplate); | 2243 frame_->Push(function_info); |
| 2245 Result answer = frame_->CallStub(&stub, 1); | 2244 Result answer = frame_->CallStub(&stub, 1); |
| 2246 frame_->Push(&answer); | 2245 frame_->Push(&answer); |
| 2247 } else { | 2246 } else { |
| 2248 // Call the runtime to instantiate the function boilerplate | 2247 // Call the runtime to instantiate the function boilerplate |
| 2249 // object. | 2248 // object. |
| 2250 frame_->EmitPush(rsi); | 2249 frame_->EmitPush(rsi); |
| 2251 frame_->EmitPush(boilerplate); | 2250 frame_->EmitPush(function_info); |
| 2252 Result result = frame_->CallRuntime(Runtime::kNewClosure, 2); | 2251 Result result = frame_->CallRuntime(Runtime::kNewClosure, 2); |
| 2253 frame_->Push(&result); | 2252 frame_->Push(&result); |
| 2254 } | 2253 } |
| 2255 } | 2254 } |
| 2256 | 2255 |
| 2257 | 2256 |
| 2258 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { | 2257 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { |
| 2259 Comment cmnt(masm_, "[ FunctionLiteral"); | 2258 Comment cmnt(masm_, "[ FunctionLiteral"); |
| 2260 | 2259 |
| 2261 // Build the function boilerplate and instantiate it. | 2260 // Build the function info and instantiate it. |
| 2262 Handle<JSFunction> boilerplate = | 2261 Handle<SharedFunctionInfo> function_info = |
| 2263 Compiler::BuildBoilerplate(node, script(), this); | 2262 Compiler::BuildFunctionInfo(node, script(), this); |
| 2264 // Check for stack-overflow exception. | 2263 // Check for stack-overflow exception. |
| 2265 if (HasStackOverflow()) return; | 2264 if (HasStackOverflow()) return; |
| 2266 InstantiateBoilerplate(boilerplate); | 2265 InstantiateFunction(function_info); |
| 2267 } | 2266 } |
| 2268 | 2267 |
| 2269 | 2268 |
| 2270 void CodeGenerator::VisitFunctionBoilerplateLiteral( | 2269 void CodeGenerator::VisitSharedFunctionInfoLiteral( |
| 2271 FunctionBoilerplateLiteral* node) { | 2270 SharedFunctionInfoLiteral* node) { |
| 2272 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); | 2271 Comment cmnt(masm_, "[ SharedFunctionInfoLiteral"); |
| 2273 InstantiateBoilerplate(node->boilerplate()); | 2272 InstantiateFunction(node->shared_function_info()); |
| 2274 } | 2273 } |
| 2275 | 2274 |
| 2276 | 2275 |
| 2277 void CodeGenerator::VisitConditional(Conditional* node) { | 2276 void CodeGenerator::VisitConditional(Conditional* node) { |
| 2278 Comment cmnt(masm_, "[ Conditional"); | 2277 Comment cmnt(masm_, "[ Conditional"); |
| 2279 JumpTarget then; | 2278 JumpTarget then; |
| 2280 JumpTarget else_; | 2279 JumpTarget else_; |
| 2281 JumpTarget exit; | 2280 JumpTarget exit; |
| 2282 ControlDestination dest(&then, &else_, true); | 2281 ControlDestination dest(&then, &else_, true); |
| 2283 LoadCondition(node->condition(), &dest, true); | 2282 LoadCondition(node->condition(), &dest, true); |
| (...skipping 4070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6354 break; | 6353 break; |
| 6355 } | 6354 } |
| 6356 | 6355 |
| 6357 default: | 6356 default: |
| 6358 UNREACHABLE(); | 6357 UNREACHABLE(); |
| 6359 } | 6358 } |
| 6360 } | 6359 } |
| 6361 | 6360 |
| 6362 | 6361 |
| 6363 void FastNewClosureStub::Generate(MacroAssembler* masm) { | 6362 void FastNewClosureStub::Generate(MacroAssembler* masm) { |
| 6364 // Clone the boilerplate in new space. Set the context to the | 6363 // Create a new closure from the given function info in new |
| 6365 // current context in rsi. | 6364 // space. Set the context to the current context in rsi. |
| 6366 Label gc; | 6365 Label gc; |
| 6367 __ AllocateInNewSpace(JSFunction::kSize, rax, rbx, rcx, &gc, TAG_OBJECT); | 6366 __ AllocateInNewSpace(JSFunction::kSize, rax, rbx, rcx, &gc, TAG_OBJECT); |
| 6368 | 6367 |
| 6369 // Get the boilerplate function from the stack. | 6368 // Get the function info from the stack. |
| 6370 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); | 6369 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); |
| 6371 | 6370 |
| 6372 // Compute the function map in the current global context and set that | 6371 // Compute the function map in the current global context and set that |
| 6373 // as the map of the allocated object. | 6372 // as the map of the allocated object. |
| 6374 __ movq(rcx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 6373 __ movq(rcx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 6375 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset)); | 6374 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset)); |
| 6376 __ movq(rcx, Operand(rcx, Context::SlotOffset(Context::FUNCTION_MAP_INDEX))); | 6375 __ movq(rcx, Operand(rcx, Context::SlotOffset(Context::FUNCTION_MAP_INDEX))); |
| 6377 __ movq(FieldOperand(rax, JSObject::kMapOffset), rcx); | 6376 __ movq(FieldOperand(rax, JSObject::kMapOffset), rcx); |
| 6378 | 6377 |
| 6379 // Clone the rest of the boilerplate fields. We don't have to update | 6378 // Initialize the rest of the function. We don't have to update the |
| 6380 // the write barrier because the allocated object is in new space. | 6379 // write barrier because the allocated object is in new space. |
| 6381 for (int offset = kPointerSize; | 6380 __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex); |
| 6382 offset < JSFunction::kSize; | 6381 __ LoadRoot(rcx, Heap::kTheHoleValueRootIndex); |
| 6383 offset += kPointerSize) { | 6382 __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), rbx); |
| 6384 if (offset == JSFunction::kContextOffset) { | 6383 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rbx); |
| 6385 __ movq(FieldOperand(rax, offset), rsi); | 6384 __ movq(FieldOperand(rax, JSFunction::kPrototypeOrInitialMapOffset), rcx); |
| 6386 } else { | 6385 __ movq(FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset), rdx); |
| 6387 __ movq(rbx, FieldOperand(rdx, offset)); | 6386 __ movq(FieldOperand(rax, JSFunction::kContextOffset), rsi); |
| 6388 __ movq(FieldOperand(rax, offset), rbx); | 6387 __ movq(FieldOperand(rax, JSFunction::kLiteralsOffset), rbx); |
| 6389 } | |
| 6390 } | |
| 6391 | 6388 |
| 6392 // Return and remove the on-stack parameter. | 6389 // Return and remove the on-stack parameter. |
| 6393 __ ret(1 * kPointerSize); | 6390 __ ret(1 * kPointerSize); |
| 6394 | 6391 |
| 6395 // Create a new closure through the slower runtime call. | 6392 // Create a new closure through the slower runtime call. |
| 6396 __ bind(&gc); | 6393 __ bind(&gc); |
| 6397 __ pop(rcx); // Temporarily remove return address. | 6394 __ pop(rcx); // Temporarily remove return address. |
| 6398 __ pop(rdx); | 6395 __ pop(rdx); |
| 6399 __ push(rsi); | 6396 __ push(rsi); |
| 6400 __ push(rdx); | 6397 __ push(rdx); |
| (...skipping 2697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9098 } | 9095 } |
| 9099 | 9096 |
| 9100 | 9097 |
| 9101 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { | 9098 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { |
| 9102 GenericBinaryOpStub stub(key, type_info); | 9099 GenericBinaryOpStub stub(key, type_info); |
| 9103 return stub.GetCode(); | 9100 return stub.GetCode(); |
| 9104 } | 9101 } |
| 9105 | 9102 |
| 9106 | 9103 |
| 9107 int CompareStub::MinorKey() { | 9104 int CompareStub::MinorKey() { |
| 9108 // Encode the three parameters in a unique 16 bit value. | 9105 // Encode the three parameters in a unique 16 bit value. To avoid duplicate |
| 9106 // stubs the never NaN NaN condition is only taken into account if the |
| 9107 // condition is equals. |
| 9109 ASSERT(static_cast<unsigned>(cc_) < (1 << 14)); | 9108 ASSERT(static_cast<unsigned>(cc_) < (1 << 14)); |
| 9110 int nnn_value = (never_nan_nan_ ? 2 : 0); | 9109 return ConditionField::encode(static_cast<unsigned>(cc_)) |
| 9111 if (cc_ != equal) nnn_value = 0; // Avoid duplicate stubs. | 9110 | StrictField::encode(strict_) |
| 9112 return (static_cast<unsigned>(cc_) << 2) | nnn_value | (strict_ ? 1 : 0); | 9111 | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false); |
| 9113 } | 9112 } |
| 9114 | 9113 |
| 9115 | 9114 |
| 9116 const char* CompareStub::GetName() { | 9115 const char* CompareStub::GetName() { |
| 9117 switch (cc_) { | 9116 switch (cc_) { |
| 9118 case less: return "CompareStub_LT"; | 9117 case less: return "CompareStub_LT"; |
| 9119 case greater: return "CompareStub_GT"; | 9118 case greater: return "CompareStub_GT"; |
| 9120 case less_equal: return "CompareStub_LE"; | 9119 case less_equal: return "CompareStub_LE"; |
| 9121 case greater_equal: return "CompareStub_GE"; | 9120 case greater_equal: return "CompareStub_GE"; |
| 9122 case not_equal: { | 9121 case not_equal: { |
| (...skipping 865 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9988 // Call the function from C++. | 9987 // Call the function from C++. |
| 9989 return FUNCTION_CAST<ModuloFunction>(buffer); | 9988 return FUNCTION_CAST<ModuloFunction>(buffer); |
| 9990 } | 9989 } |
| 9991 | 9990 |
| 9992 #endif | 9991 #endif |
| 9993 | 9992 |
| 9994 | 9993 |
| 9995 #undef __ | 9994 #undef __ |
| 9996 | 9995 |
| 9997 } } // namespace v8::internal | 9996 } } // namespace v8::internal |
| OLD | NEW |