| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 isolate()->GetHTracer()->TraceCompilation(&info_); | 143 isolate()->GetHTracer()->TraceCompilation(&info_); |
| 144 } | 144 } |
| 145 | 145 |
| 146 int param_count = descriptor_->register_param_count_; | 146 int param_count = descriptor_->register_param_count_; |
| 147 HEnvironment* start_environment = graph()->start_environment(); | 147 HEnvironment* start_environment = graph()->start_environment(); |
| 148 HBasicBlock* next_block = CreateBasicBlock(start_environment); | 148 HBasicBlock* next_block = CreateBasicBlock(start_environment); |
| 149 Goto(next_block); | 149 Goto(next_block); |
| 150 next_block->SetJoinId(BailoutId::StubEntry()); | 150 next_block->SetJoinId(BailoutId::StubEntry()); |
| 151 set_current_block(next_block); | 151 set_current_block(next_block); |
| 152 | 152 |
| 153 bool runtime_stack_params = descriptor_->stack_parameter_count_.is_valid(); |
| 154 HInstruction* stack_parameter_count = NULL; |
| 153 for (int i = 0; i < param_count; ++i) { | 155 for (int i = 0; i < param_count; ++i) { |
| 154 HParameter* param = | 156 Representation r = descriptor_->IsParameterCountRegister(i) |
| 155 Add<HParameter>(i, HParameter::REGISTER_PARAMETER); | 157 ? Representation::Integer32() |
| 158 : Representation::Tagged(); |
| 159 HParameter* param = Add<HParameter>(i, HParameter::REGISTER_PARAMETER, r); |
| 156 start_environment->Bind(i, param); | 160 start_environment->Bind(i, param); |
| 157 parameters_[i] = param; | 161 parameters_[i] = param; |
| 162 if (descriptor_->IsParameterCountRegister(i)) { |
| 163 param->set_type(HType::Smi()); |
| 164 stack_parameter_count = param; |
| 165 arguments_length_ = stack_parameter_count; |
| 166 } |
| 158 } | 167 } |
| 159 | 168 |
| 160 HInstruction* stack_parameter_count; | 169 ASSERT(!runtime_stack_params || arguments_length_ != NULL); |
| 161 if (descriptor_->stack_parameter_count_.is_valid()) { | 170 if (!runtime_stack_params) { |
| 162 ASSERT(descriptor_->environment_length() == (param_count + 1)); | |
| 163 stack_parameter_count = New<HParameter>(param_count, | |
| 164 HParameter::REGISTER_PARAMETER, | |
| 165 Representation::Integer32()); | |
| 166 stack_parameter_count->set_type(HType::Smi()); | |
| 167 // It's essential to bind this value to the environment in case of deopt. | |
| 168 AddInstruction(stack_parameter_count); | |
| 169 start_environment->Bind(param_count, stack_parameter_count); | |
| 170 arguments_length_ = stack_parameter_count; | |
| 171 } else { | |
| 172 ASSERT(descriptor_->environment_length() == param_count); | |
| 173 stack_parameter_count = graph()->GetConstantMinus1(); | 171 stack_parameter_count = graph()->GetConstantMinus1(); |
| 174 arguments_length_ = graph()->GetConstant0(); | 172 arguments_length_ = graph()->GetConstant0(); |
| 175 } | 173 } |
| 176 | 174 |
| 177 context_ = Add<HContext>(); | 175 context_ = Add<HContext>(); |
| 178 start_environment->BindContext(context_); | 176 start_environment->BindContext(context_); |
| 179 | 177 |
| 180 Add<HSimulate>(BailoutId::StubEntry()); | 178 Add<HSimulate>(BailoutId::StubEntry()); |
| 181 | 179 |
| 182 NoObservableSideEffectsScope no_effects(this); | 180 NoObservableSideEffectsScope no_effects(this); |
| 183 | 181 |
| 184 HValue* return_value = BuildCodeStub(); | 182 HValue* return_value = BuildCodeStub(); |
| 185 | 183 |
| 186 // We might have extra expressions to pop from the stack in addition to the | 184 // We might have extra expressions to pop from the stack in addition to the |
| 187 // arguments above. | 185 // arguments above. |
| 188 HInstruction* stack_pop_count = stack_parameter_count; | 186 HInstruction* stack_pop_count = stack_parameter_count; |
| 189 if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) { | 187 if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) { |
| 190 if (!stack_parameter_count->IsConstant() && | 188 if (!stack_parameter_count->IsConstant() && |
| 191 descriptor_->hint_stack_parameter_count_ < 0) { | 189 descriptor_->hint_stack_parameter_count_ < 0) { |
| 192 HInstruction* amount = graph()->GetConstant1(); | 190 HInstruction* constant_one = graph()->GetConstant1(); |
| 193 stack_pop_count = Add<HAdd>(stack_parameter_count, amount); | 191 stack_pop_count = Add<HAdd>(stack_parameter_count, constant_one); |
| 194 stack_pop_count->ChangeRepresentation(Representation::Integer32()); | |
| 195 stack_pop_count->ClearFlag(HValue::kCanOverflow); | 192 stack_pop_count->ClearFlag(HValue::kCanOverflow); |
| 193 // TODO(mvstanton): verify that stack_parameter_count+1 really fits in a |
| 194 // smi. |
| 196 } else { | 195 } else { |
| 197 int count = descriptor_->hint_stack_parameter_count_; | 196 int count = descriptor_->hint_stack_parameter_count_; |
| 198 stack_pop_count = Add<HConstant>(count); | 197 stack_pop_count = Add<HConstant>(count); |
| 199 } | 198 } |
| 200 } | 199 } |
| 201 | 200 |
| 202 if (current_block() != NULL) { | 201 if (current_block() != NULL) { |
| 203 HReturn* hreturn_instruction = New<HReturn>(return_value, | 202 HReturn* hreturn_instruction = New<HReturn>(return_value, |
| 204 stack_pop_count); | 203 stack_pop_count); |
| 205 FinishCurrentBlock(hreturn_instruction); | 204 FinishCurrentBlock(hreturn_instruction); |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 | 363 |
| 365 HInstruction* allocation_site = Add<HLoadKeyed>(GetParameter(0), | 364 HInstruction* allocation_site = Add<HLoadKeyed>(GetParameter(0), |
| 366 GetParameter(1), | 365 GetParameter(1), |
| 367 static_cast<HValue*>(NULL), | 366 static_cast<HValue*>(NULL), |
| 368 FAST_ELEMENTS); | 367 FAST_ELEMENTS); |
| 369 IfBuilder checker(this); | 368 IfBuilder checker(this); |
| 370 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, | 369 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, |
| 371 undefined); | 370 undefined); |
| 372 checker.Then(); | 371 checker.Then(); |
| 373 | 372 |
| 374 HObjectAccess access = HObjectAccess::ForAllocationSiteTransitionInfo(); | 373 HObjectAccess access = HObjectAccess::ForAllocationSiteOffset( |
| 374 AllocationSite::kTransitionInfoOffset); |
| 375 HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access); | 375 HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access); |
| 376 HValue* push_value; | 376 HValue* push_value; |
| 377 if (mode == FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS) { | 377 if (mode == FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS) { |
| 378 HValue* elements = AddLoadElements(boilerplate); | 378 HValue* elements = AddLoadElements(boilerplate); |
| 379 | 379 |
| 380 IfBuilder if_fixed_cow(this); | 380 IfBuilder if_fixed_cow(this); |
| 381 if_fixed_cow.If<HCompareMap>(elements, factory->fixed_cow_array_map()); | 381 if_fixed_cow.If<HCompareMap>(elements, factory->fixed_cow_array_map()); |
| 382 if_fixed_cow.Then(); | 382 if_fixed_cow.Then(); |
| 383 push_value = BuildCloneShallowArray(boilerplate, | 383 push_value = BuildCloneShallowArray(boilerplate, |
| 384 allocation_site, | 384 allocation_site, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 HInstruction* allocation_site = Add<HLoadKeyed>(GetParameter(0), | 433 HInstruction* allocation_site = Add<HLoadKeyed>(GetParameter(0), |
| 434 GetParameter(1), | 434 GetParameter(1), |
| 435 static_cast<HValue*>(NULL), | 435 static_cast<HValue*>(NULL), |
| 436 FAST_ELEMENTS); | 436 FAST_ELEMENTS); |
| 437 | 437 |
| 438 IfBuilder checker(this); | 438 IfBuilder checker(this); |
| 439 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, | 439 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, |
| 440 undefined); | 440 undefined); |
| 441 checker.And(); | 441 checker.And(); |
| 442 | 442 |
| 443 HObjectAccess access = HObjectAccess::ForAllocationSiteTransitionInfo(); | 443 HObjectAccess access = HObjectAccess::ForAllocationSiteOffset( |
| 444 AllocationSite::kTransitionInfoOffset); |
| 444 HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access); | 445 HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access); |
| 445 | 446 |
| 446 int size = JSObject::kHeaderSize + casted_stub()->length() * kPointerSize; | 447 int size = JSObject::kHeaderSize + casted_stub()->length() * kPointerSize; |
| 447 int object_size = size; | 448 int object_size = size; |
| 448 if (FLAG_allocation_site_pretenuring) { | 449 if (FLAG_allocation_site_pretenuring) { |
| 449 size += AllocationMemento::kSize; | 450 size += AllocationMemento::kSize; |
| 450 } | 451 } |
| 451 | 452 |
| 452 HValue* boilerplate_map = Add<HLoadNamedField>( | 453 HValue* boilerplate_map = Add<HLoadNamedField>( |
| 453 boilerplate, HObjectAccess::ForMap()); | 454 boilerplate, HObjectAccess::ForMap()); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 HInstruction* object = Add<HAllocate>(size, HType::JSObject(), TENURED, | 494 HInstruction* object = Add<HAllocate>(size, HType::JSObject(), TENURED, |
| 494 JS_OBJECT_TYPE); | 495 JS_OBJECT_TYPE); |
| 495 | 496 |
| 496 // Store the map | 497 // Store the map |
| 497 Handle<Map> allocation_site_map = isolate()->factory()->allocation_site_map(); | 498 Handle<Map> allocation_site_map = isolate()->factory()->allocation_site_map(); |
| 498 AddStoreMapConstant(object, allocation_site_map); | 499 AddStoreMapConstant(object, allocation_site_map); |
| 499 | 500 |
| 500 // Store the payload (smi elements kind) | 501 // Store the payload (smi elements kind) |
| 501 HValue* initial_elements_kind = Add<HConstant>(GetInitialFastElementsKind()); | 502 HValue* initial_elements_kind = Add<HConstant>(GetInitialFastElementsKind()); |
| 502 Add<HStoreNamedField>(object, | 503 Add<HStoreNamedField>(object, |
| 503 HObjectAccess::ForAllocationSiteTransitionInfo(), | 504 HObjectAccess::ForAllocationSiteOffset( |
| 505 AllocationSite::kTransitionInfoOffset), |
| 504 initial_elements_kind); | 506 initial_elements_kind); |
| 505 | 507 |
| 506 // Unlike literals, constructed arrays don't have nested sites | 508 // Unlike literals, constructed arrays don't have nested sites |
| 507 Add<HStoreNamedField>(object, | 509 Add<HStoreNamedField>(object, |
| 508 HObjectAccess::ForAllocationSiteNestedSite(), | 510 HObjectAccess::ForAllocationSiteOffset( |
| 511 AllocationSite::kNestedSiteOffset), |
| 509 graph()->GetConstant0()); | 512 graph()->GetConstant0()); |
| 510 | 513 |
| 511 // Store an empty fixed array for the code dependency. | 514 // Store an empty fixed array for the code dependency. |
| 512 HConstant* empty_fixed_array = | 515 HConstant* empty_fixed_array = |
| 513 Add<HConstant>(isolate()->factory()->empty_fixed_array()); | 516 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
| 514 HStoreNamedField* store = Add<HStoreNamedField>( | 517 HStoreNamedField* store = Add<HStoreNamedField>( |
| 515 object, | 518 object, |
| 516 HObjectAccess::ForAllocationSiteDependentCode(), | 519 HObjectAccess::ForAllocationSiteOffset( |
| 520 AllocationSite::kDependentCodeOffset), |
| 517 empty_fixed_array); | 521 empty_fixed_array); |
| 518 | 522 |
| 519 // Link the object to the allocation site list | 523 // Link the object to the allocation site list |
| 520 HValue* site_list = Add<HConstant>( | 524 HValue* site_list = Add<HConstant>( |
| 521 ExternalReference::allocation_sites_list_address(isolate())); | 525 ExternalReference::allocation_sites_list_address(isolate())); |
| 522 HValue* site = Add<HLoadNamedField>(site_list, | 526 HValue* site = Add<HLoadNamedField>(site_list, |
| 523 HObjectAccess::ForAllocationSiteList()); | 527 HObjectAccess::ForAllocationSiteList()); |
| 524 store = Add<HStoreNamedField>(object, | 528 store = Add<HStoreNamedField>(object, |
| 525 HObjectAccess::ForAllocationSiteWeakNext(), | 529 HObjectAccess::ForAllocationSiteOffset(AllocationSite::kWeakNextOffset), |
| 526 site); | 530 site); |
| 527 store->SkipWriteBarrier(); | 531 store->SkipWriteBarrier(); |
| 528 Add<HStoreNamedField>(site_list, HObjectAccess::ForAllocationSiteList(), | 532 Add<HStoreNamedField>(site_list, HObjectAccess::ForAllocationSiteList(), |
| 529 object); | 533 object); |
| 530 | 534 |
| 531 // We use a hammer (SkipWriteBarrier()) to indicate that we know the input | 535 // We use a hammer (SkipWriteBarrier()) to indicate that we know the input |
| 532 // cell is really a Cell, and so no write barrier is needed. | 536 // cell is really a Cell, and so no write barrier is needed. |
| 533 // TODO(mvstanton): Add a debug_code check to verify the input cell is really | 537 // TODO(mvstanton): Add a debug_code check to verify the input cell is really |
| 534 // a cell. (perhaps with a new instruction, HAssert). | 538 // a cell. (perhaps with a new instruction, HAssert). |
| 535 HInstruction* cell = GetParameter(0); | 539 HInstruction* cell = GetParameter(0); |
| 536 HObjectAccess access = HObjectAccess::ForCellValue(); | 540 HObjectAccess access = HObjectAccess::ForCellValue(); |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 960 return result; | 964 return result; |
| 961 } | 965 } |
| 962 | 966 |
| 963 | 967 |
| 964 Handle<Code> BinaryOpStub::GenerateCode(Isolate* isolate) { | 968 Handle<Code> BinaryOpStub::GenerateCode(Isolate* isolate) { |
| 965 return DoGenerateCode(isolate, this); | 969 return DoGenerateCode(isolate, this); |
| 966 } | 970 } |
| 967 | 971 |
| 968 | 972 |
| 969 template <> | 973 template <> |
| 974 HValue* CodeStubGraphBuilder<NewStringAddStub>::BuildCodeInitializedStub() { |
| 975 NewStringAddStub* stub = casted_stub(); |
| 976 StringAddFlags flags = stub->flags(); |
| 977 PretenureFlag pretenure_flag = stub->pretenure_flag(); |
| 978 |
| 979 HValue* left = GetParameter(NewStringAddStub::kLeft); |
| 980 HValue* right = GetParameter(NewStringAddStub::kRight); |
| 981 |
| 982 // Make sure that both arguments are strings if not known in advance. |
| 983 if ((flags & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) { |
| 984 IfBuilder if_leftnotstring(this); |
| 985 if_leftnotstring.IfNot<HIsStringAndBranch>(left); |
| 986 if_leftnotstring.Then(); |
| 987 if_leftnotstring.Deopt("Expected string for LHS of string addition"); |
| 988 } |
| 989 if ((flags & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) { |
| 990 IfBuilder if_rightnotstring(this); |
| 991 if_rightnotstring.IfNot<HIsStringAndBranch>(right); |
| 992 if_rightnotstring.Then(); |
| 993 if_rightnotstring.Deopt("Expected string for RHS of string addition"); |
| 994 } |
| 995 |
| 996 return BuildStringAdd(left, right, pretenure_flag); |
| 997 } |
| 998 |
| 999 |
| 1000 Handle<Code> NewStringAddStub::GenerateCode(Isolate* isolate) { |
| 1001 return DoGenerateCode(isolate, this); |
| 1002 } |
| 1003 |
| 1004 |
| 1005 template <> |
| 970 HValue* CodeStubGraphBuilder<ToBooleanStub>::BuildCodeInitializedStub() { | 1006 HValue* CodeStubGraphBuilder<ToBooleanStub>::BuildCodeInitializedStub() { |
| 971 ToBooleanStub* stub = casted_stub(); | 1007 ToBooleanStub* stub = casted_stub(); |
| 972 | 1008 |
| 973 IfBuilder if_true(this); | 1009 IfBuilder if_true(this); |
| 974 if_true.If<HBranch>(GetParameter(0), stub->GetTypes()); | 1010 if_true.If<HBranch>(GetParameter(0), stub->GetTypes()); |
| 975 if_true.Then(); | 1011 if_true.Then(); |
| 976 if_true.Return(graph()->GetConstant1()); | 1012 if_true.Return(graph()->GetConstant1()); |
| 977 if_true.Else(); | 1013 if_true.Else(); |
| 978 if_true.End(); | 1014 if_true.End(); |
| 979 return graph()->GetConstant0(); | 1015 return graph()->GetConstant0(); |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1229 Add<HStoreNamedField>(js_function, HObjectAccess::ForElementsPointer(), | 1265 Add<HStoreNamedField>(js_function, HObjectAccess::ForElementsPointer(), |
| 1230 empty_fixed_array); | 1266 empty_fixed_array); |
| 1231 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), | 1267 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), |
| 1232 empty_fixed_array); | 1268 empty_fixed_array); |
| 1233 Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(), | 1269 Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(), |
| 1234 graph()->GetConstantHole()); | 1270 graph()->GetConstantHole()); |
| 1235 Add<HStoreNamedField>(js_function, | 1271 Add<HStoreNamedField>(js_function, |
| 1236 HObjectAccess::ForSharedFunctionInfoPointer(), | 1272 HObjectAccess::ForSharedFunctionInfoPointer(), |
| 1237 shared_info); | 1273 shared_info); |
| 1238 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(), | 1274 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(), |
| 1239 shared_info); | |
| 1240 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(), | |
| 1241 context()); | 1275 context()); |
| 1242 | 1276 |
| 1243 // Initialize the code pointer in the function to be the one | 1277 // Initialize the code pointer in the function to be the one |
| 1244 // found in the shared function info object. | 1278 // found in the shared function info object. |
| 1245 // But first check if there is an optimized version for our context. | 1279 // But first check if there is an optimized version for our context. |
| 1246 if (FLAG_cache_optimized_code) { | 1280 if (FLAG_cache_optimized_code) { |
| 1247 BuildInstallFromOptimizedCodeMap(js_function, shared_info, native_context); | 1281 BuildInstallFromOptimizedCodeMap(js_function, shared_info, native_context); |
| 1248 } else { | 1282 } else { |
| 1249 BuildInstallCode(js_function, shared_info); | 1283 BuildInstallCode(js_function, shared_info); |
| 1250 } | 1284 } |
| 1251 | 1285 |
| 1252 return js_function; | 1286 return js_function; |
| 1253 } | 1287 } |
| 1254 | 1288 |
| 1255 | 1289 |
| 1256 Handle<Code> FastNewClosureStub::GenerateCode(Isolate* isolate) { | 1290 Handle<Code> FastNewClosureStub::GenerateCode(Isolate* isolate) { |
| 1257 return DoGenerateCode(isolate, this); | 1291 return DoGenerateCode(isolate, this); |
| 1258 } | 1292 } |
| 1259 | 1293 |
| 1260 | 1294 |
| 1261 } } // namespace v8::internal | 1295 } } // namespace v8::internal |
| OLD | NEW |