| 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 23 matching lines...) Expand all Loading... |
| 34 namespace v8 { | 34 namespace v8 { |
| 35 namespace internal { | 35 namespace internal { |
| 36 | 36 |
| 37 | 37 |
| 38 static LChunk* OptimizeGraph(HGraph* graph) { | 38 static LChunk* OptimizeGraph(HGraph* graph) { |
| 39 DisallowHeapAllocation no_allocation; | 39 DisallowHeapAllocation no_allocation; |
| 40 DisallowHandleAllocation no_handles; | 40 DisallowHandleAllocation no_handles; |
| 41 DisallowHandleDereference no_deref; | 41 DisallowHandleDereference no_deref; |
| 42 | 42 |
| 43 ASSERT(graph != NULL); | 43 ASSERT(graph != NULL); |
| 44 SmartArrayPointer<char> bailout_reason; | 44 BailoutReason bailout_reason = kNoReason; |
| 45 if (!graph->Optimize(&bailout_reason)) { | 45 if (!graph->Optimize(&bailout_reason)) { |
| 46 FATAL(bailout_reason.is_empty() ? "unknown" : *bailout_reason); | 46 FATAL(GetBailoutReason(bailout_reason)); |
| 47 } | 47 } |
| 48 LChunk* chunk = LChunk::NewChunk(graph); | 48 LChunk* chunk = LChunk::NewChunk(graph); |
| 49 if (chunk == NULL) { | 49 if (chunk == NULL) { |
| 50 FATAL(graph->info()->bailout_reason()); | 50 FATAL(GetBailoutReason(graph->info()->bailout_reason())); |
| 51 } | 51 } |
| 52 return chunk; | 52 return chunk; |
| 53 } | 53 } |
| 54 | 54 |
| 55 | 55 |
| 56 class CodeStubGraphBuilderBase : public HGraphBuilder { | 56 class CodeStubGraphBuilderBase : public HGraphBuilder { |
| 57 public: | 57 public: |
| 58 CodeStubGraphBuilderBase(Isolate* isolate, HydrogenCodeStub* stub) | 58 CodeStubGraphBuilderBase(Isolate* isolate, HydrogenCodeStub* stub) |
| 59 : HGraphBuilder(&info_), | 59 : HGraphBuilder(&info_), |
| 60 arguments_length_(NULL), | 60 arguments_length_(NULL), |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 // Update the static counter each time a new code stub is generated. | 129 // Update the static counter each time a new code stub is generated. |
| 130 isolate()->counters()->code_stubs()->Increment(); | 130 isolate()->counters()->code_stubs()->Increment(); |
| 131 | 131 |
| 132 if (FLAG_trace_hydrogen_stubs) { | 132 if (FLAG_trace_hydrogen_stubs) { |
| 133 const char* name = CodeStub::MajorName(stub()->MajorKey(), false); | 133 const char* name = CodeStub::MajorName(stub()->MajorKey(), false); |
| 134 PrintF("-----------------------------------------------------------\n"); | 134 PrintF("-----------------------------------------------------------\n"); |
| 135 PrintF("Compiling stub %s using hydrogen\n", name); | 135 PrintF("Compiling stub %s using hydrogen\n", name); |
| 136 isolate()->GetHTracer()->TraceCompilation(&info_); | 136 isolate()->GetHTracer()->TraceCompilation(&info_); |
| 137 } | 137 } |
| 138 | 138 |
| 139 Zone* zone = this->zone(); | |
| 140 int param_count = descriptor_->register_param_count_; | 139 int param_count = descriptor_->register_param_count_; |
| 141 HEnvironment* start_environment = graph()->start_environment(); | 140 HEnvironment* start_environment = graph()->start_environment(); |
| 142 HBasicBlock* next_block = CreateBasicBlock(start_environment); | 141 HBasicBlock* next_block = CreateBasicBlock(start_environment); |
| 143 current_block()->Goto(next_block); | 142 current_block()->Goto(next_block); |
| 144 next_block->SetJoinId(BailoutId::StubEntry()); | 143 next_block->SetJoinId(BailoutId::StubEntry()); |
| 145 set_current_block(next_block); | 144 set_current_block(next_block); |
| 146 | 145 |
| 147 HConstant* undefined_constant = new(zone) HConstant( | 146 HConstant* undefined_constant = |
| 148 isolate()->factory()->undefined_value()); | 147 Add<HConstant>(isolate()->factory()->undefined_value()); |
| 149 AddInstruction(undefined_constant); | |
| 150 graph()->set_undefined_constant(undefined_constant); | 148 graph()->set_undefined_constant(undefined_constant); |
| 151 | 149 |
| 152 for (int i = 0; i < param_count; ++i) { | 150 for (int i = 0; i < param_count; ++i) { |
| 153 HParameter* param = | 151 HParameter* param = |
| 154 new(zone) HParameter(i, HParameter::REGISTER_PARAMETER); | 152 Add<HParameter>(i, HParameter::REGISTER_PARAMETER); |
| 155 AddInstruction(param); | |
| 156 start_environment->Bind(i, param); | 153 start_environment->Bind(i, param); |
| 157 parameters_[i] = param; | 154 parameters_[i] = param; |
| 158 } | 155 } |
| 159 | 156 |
| 160 HInstruction* stack_parameter_count; | 157 HInstruction* stack_parameter_count; |
| 161 if (descriptor_->stack_parameter_count_ != NULL) { | 158 if (descriptor_->stack_parameter_count_ != NULL) { |
| 162 ASSERT(descriptor_->environment_length() == (param_count + 1)); | 159 ASSERT(descriptor_->environment_length() == (param_count + 1)); |
| 163 stack_parameter_count = new(zone) HParameter(param_count, | 160 stack_parameter_count = New<HParameter>(param_count, |
| 164 HParameter::REGISTER_PARAMETER, | 161 HParameter::REGISTER_PARAMETER, |
| 165 Representation::Integer32()); | 162 Representation::Integer32()); |
| 166 stack_parameter_count->set_type(HType::Smi()); | 163 stack_parameter_count->set_type(HType::Smi()); |
| 167 // It's essential to bind this value to the environment in case of deopt. | 164 // It's essential to bind this value to the environment in case of deopt. |
| 168 AddInstruction(stack_parameter_count); | 165 AddInstruction(stack_parameter_count); |
| 169 start_environment->Bind(param_count, stack_parameter_count); | 166 start_environment->Bind(param_count, stack_parameter_count); |
| 170 arguments_length_ = stack_parameter_count; | 167 arguments_length_ = stack_parameter_count; |
| 171 } else { | 168 } else { |
| 172 ASSERT(descriptor_->environment_length() == param_count); | 169 ASSERT(descriptor_->environment_length() == param_count); |
| 173 stack_parameter_count = graph()->GetConstantMinus1(); | 170 stack_parameter_count = graph()->GetConstantMinus1(); |
| 174 arguments_length_ = graph()->GetConstant0(); | 171 arguments_length_ = graph()->GetConstant0(); |
| 175 } | 172 } |
| 176 | 173 |
| 177 context_ = new(zone) HContext(); | 174 context_ = New<HContext>(); |
| 178 AddInstruction(context_); | 175 AddInstruction(context_); |
| 179 start_environment->BindContext(context_); | 176 start_environment->BindContext(context_); |
| 180 | 177 |
| 181 Add<HSimulate>(BailoutId::StubEntry()); | 178 Add<HSimulate>(BailoutId::StubEntry()); |
| 182 | 179 |
| 183 NoObservableSideEffectsScope no_effects(this); | 180 NoObservableSideEffectsScope no_effects(this); |
| 184 | 181 |
| 185 HValue* return_value = BuildCodeStub(); | 182 HValue* return_value = BuildCodeStub(); |
| 186 | 183 |
| 187 // 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 |
| 188 // arguments above. | 185 // arguments above. |
| 189 HInstruction* stack_pop_count = stack_parameter_count; | 186 HInstruction* stack_pop_count = stack_parameter_count; |
| 190 if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) { | 187 if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) { |
| 191 if (!stack_parameter_count->IsConstant() && | 188 if (!stack_parameter_count->IsConstant() && |
| 192 descriptor_->hint_stack_parameter_count_ < 0) { | 189 descriptor_->hint_stack_parameter_count_ < 0) { |
| 193 HInstruction* amount = graph()->GetConstant1(); | 190 HInstruction* amount = graph()->GetConstant1(); |
| 194 stack_pop_count = AddInstruction( | 191 stack_pop_count = Add<HAdd>(stack_parameter_count, amount); |
| 195 HAdd::New(zone, context_, stack_parameter_count, amount)); | |
| 196 stack_pop_count->ChangeRepresentation(Representation::Integer32()); | 192 stack_pop_count->ChangeRepresentation(Representation::Integer32()); |
| 197 stack_pop_count->ClearFlag(HValue::kCanOverflow); | 193 stack_pop_count->ClearFlag(HValue::kCanOverflow); |
| 198 } else { | 194 } else { |
| 199 int count = descriptor_->hint_stack_parameter_count_; | 195 int count = descriptor_->hint_stack_parameter_count_; |
| 200 stack_pop_count = AddInstruction(new(zone) HConstant(count)); | 196 stack_pop_count = Add<HConstant>(count); |
| 201 } | 197 } |
| 202 } | 198 } |
| 203 | 199 |
| 204 if (current_block() != NULL) { | 200 if (current_block() != NULL) { |
| 205 HReturn* hreturn_instruction = new(zone) HReturn(return_value, | 201 HReturn* hreturn_instruction = New<HReturn>(return_value, |
| 206 context_, | 202 stack_pop_count); |
| 207 stack_pop_count); | |
| 208 current_block()->Finish(hreturn_instruction); | 203 current_block()->Finish(hreturn_instruction); |
| 209 set_current_block(NULL); | 204 set_current_block(NULL); |
| 210 } | 205 } |
| 211 return true; | 206 return true; |
| 212 } | 207 } |
| 213 | 208 |
| 214 | 209 |
| 215 template <class Stub> | 210 template <class Stub> |
| 216 class CodeStubGraphBuilder: public CodeStubGraphBuilderBase { | 211 class CodeStubGraphBuilder: public CodeStubGraphBuilderBase { |
| 217 public: | 212 public: |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 if_number.If<HIsSmiAndBranch>(value); | 310 if_number.If<HIsSmiAndBranch>(value); |
| 316 if_number.OrIf<HCompareMap>(value, isolate()->factory()->heap_number_map()); | 311 if_number.OrIf<HCompareMap>(value, isolate()->factory()->heap_number_map()); |
| 317 if_number.Then(); | 312 if_number.Then(); |
| 318 | 313 |
| 319 // Return the number. | 314 // Return the number. |
| 320 Push(value); | 315 Push(value); |
| 321 | 316 |
| 322 if_number.Else(); | 317 if_number.Else(); |
| 323 | 318 |
| 324 // Convert the parameter to number using the builtin. | 319 // Convert the parameter to number using the builtin. |
| 325 HValue* function = AddLoadJSBuiltin(Builtins::TO_NUMBER, context()); | 320 HValue* function = AddLoadJSBuiltin(Builtins::TO_NUMBER); |
| 326 Add<HPushArgument>(value); | 321 Add<HPushArgument>(value); |
| 327 Push(Add<HInvokeFunction>(context(), function, 1)); | 322 Push(Add<HInvokeFunction>(function, 1)); |
| 328 | 323 |
| 329 if_number.End(); | 324 if_number.End(); |
| 330 | 325 |
| 331 return Pop(); | 326 return Pop(); |
| 332 } | 327 } |
| 333 | 328 |
| 334 | 329 |
| 335 Handle<Code> ToNumberStub::GenerateCode() { | 330 Handle<Code> ToNumberStub::GenerateCode() { |
| 336 return DoGenerateCode(this); | 331 return DoGenerateCode(this); |
| 337 } | 332 } |
| 338 | 333 |
| 339 | 334 |
| 340 template <> | 335 template <> |
| 341 HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() { | 336 HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() { |
| 342 Zone* zone = this->zone(); | |
| 343 Factory* factory = isolate()->factory(); | 337 Factory* factory = isolate()->factory(); |
| 344 HValue* undefined = graph()->GetConstantUndefined(); | 338 HValue* undefined = graph()->GetConstantUndefined(); |
| 345 AllocationSiteMode alloc_site_mode = casted_stub()->allocation_site_mode(); | 339 AllocationSiteMode alloc_site_mode = casted_stub()->allocation_site_mode(); |
| 346 FastCloneShallowArrayStub::Mode mode = casted_stub()->mode(); | 340 FastCloneShallowArrayStub::Mode mode = casted_stub()->mode(); |
| 347 int length = casted_stub()->length(); | 341 int length = casted_stub()->length(); |
| 348 | 342 |
| 349 HInstruction* allocation_site = | 343 HInstruction* allocation_site = Add<HLoadKeyed>(GetParameter(0), |
| 350 AddInstruction(new(zone) HLoadKeyed(GetParameter(0), | 344 GetParameter(1), |
| 351 GetParameter(1), | 345 static_cast<HValue*>(NULL), |
| 352 NULL, | 346 FAST_ELEMENTS); |
| 353 FAST_ELEMENTS)); | |
| 354 IfBuilder checker(this); | 347 IfBuilder checker(this); |
| 355 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, undefined); | 348 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, |
| 349 undefined); |
| 356 checker.Then(); | 350 checker.Then(); |
| 357 | 351 |
| 358 HObjectAccess access = HObjectAccess::ForAllocationSiteTransitionInfo(); | 352 HObjectAccess access = HObjectAccess::ForAllocationSiteTransitionInfo(); |
| 359 HInstruction* boilerplate = AddLoad(allocation_site, access); | 353 HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access); |
| 360 if (mode == FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS) { | 354 if (mode == FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS) { |
| 361 HValue* elements = AddLoadElements(boilerplate); | 355 HValue* elements = AddLoadElements(boilerplate); |
| 362 | 356 |
| 363 IfBuilder if_fixed_cow(this); | 357 IfBuilder if_fixed_cow(this); |
| 364 if_fixed_cow.If<HCompareMap>(elements, factory->fixed_cow_array_map()); | 358 if_fixed_cow.If<HCompareMap>(elements, factory->fixed_cow_array_map()); |
| 365 if_fixed_cow.Then(); | 359 if_fixed_cow.Then(); |
| 366 environment()->Push(BuildCloneShallowArray(context(), | 360 environment()->Push(BuildCloneShallowArray(boilerplate, |
| 367 boilerplate, | |
| 368 allocation_site, | 361 allocation_site, |
| 369 alloc_site_mode, | 362 alloc_site_mode, |
| 370 FAST_ELEMENTS, | 363 FAST_ELEMENTS, |
| 371 0/*copy-on-write*/)); | 364 0/*copy-on-write*/)); |
| 372 if_fixed_cow.Else(); | 365 if_fixed_cow.Else(); |
| 373 | 366 |
| 374 IfBuilder if_fixed(this); | 367 IfBuilder if_fixed(this); |
| 375 if_fixed.If<HCompareMap>(elements, factory->fixed_array_map()); | 368 if_fixed.If<HCompareMap>(elements, factory->fixed_array_map()); |
| 376 if_fixed.Then(); | 369 if_fixed.Then(); |
| 377 environment()->Push(BuildCloneShallowArray(context(), | 370 environment()->Push(BuildCloneShallowArray(boilerplate, |
| 378 boilerplate, | |
| 379 allocation_site, | 371 allocation_site, |
| 380 alloc_site_mode, | 372 alloc_site_mode, |
| 381 FAST_ELEMENTS, | 373 FAST_ELEMENTS, |
| 382 length)); | 374 length)); |
| 383 if_fixed.Else(); | 375 if_fixed.Else(); |
| 384 environment()->Push(BuildCloneShallowArray(context(), | 376 environment()->Push(BuildCloneShallowArray(boilerplate, |
| 385 boilerplate, | |
| 386 allocation_site, | 377 allocation_site, |
| 387 alloc_site_mode, | 378 alloc_site_mode, |
| 388 FAST_DOUBLE_ELEMENTS, | 379 FAST_DOUBLE_ELEMENTS, |
| 389 length)); | 380 length)); |
| 390 } else { | 381 } else { |
| 391 ElementsKind elements_kind = casted_stub()->ComputeElementsKind(); | 382 ElementsKind elements_kind = casted_stub()->ComputeElementsKind(); |
| 392 environment()->Push(BuildCloneShallowArray(context(), | 383 environment()->Push(BuildCloneShallowArray(boilerplate, |
| 393 boilerplate, | |
| 394 allocation_site, | 384 allocation_site, |
| 395 alloc_site_mode, | 385 alloc_site_mode, |
| 396 elements_kind, | 386 elements_kind, |
| 397 length)); | 387 length)); |
| 398 } | 388 } |
| 399 | 389 |
| 400 checker.ElseDeopt(); | 390 checker.ElseDeopt(); |
| 401 checker.End(); | 391 checker.End(); |
| 402 | 392 |
| 403 return environment()->Pop(); | 393 return environment()->Pop(); |
| 404 } | 394 } |
| 405 | 395 |
| 406 | 396 |
| 407 Handle<Code> FastCloneShallowArrayStub::GenerateCode() { | 397 Handle<Code> FastCloneShallowArrayStub::GenerateCode() { |
| 408 return DoGenerateCode(this); | 398 return DoGenerateCode(this); |
| 409 } | 399 } |
| 410 | 400 |
| 411 | 401 |
| 412 template <> | 402 template <> |
| 413 HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() { | 403 HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() { |
| 414 Zone* zone = this->zone(); | 404 Zone* zone = this->zone(); |
| 415 HValue* undefined = graph()->GetConstantUndefined(); | 405 HValue* undefined = graph()->GetConstantUndefined(); |
| 416 | 406 |
| 417 HInstruction* boilerplate = | 407 HInstruction* boilerplate = Add<HLoadKeyed>(GetParameter(0), |
| 418 AddInstruction(new(zone) HLoadKeyed(GetParameter(0), | 408 GetParameter(1), |
| 419 GetParameter(1), | 409 static_cast<HValue*>(NULL), |
| 420 NULL, | 410 FAST_ELEMENTS); |
| 421 FAST_ELEMENTS)); | |
| 422 | 411 |
| 423 IfBuilder checker(this); | 412 IfBuilder checker(this); |
| 424 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(boilerplate, undefined); | 413 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(boilerplate, |
| 414 undefined); |
| 425 checker.And(); | 415 checker.And(); |
| 426 | 416 |
| 427 int size = JSObject::kHeaderSize + casted_stub()->length() * kPointerSize; | 417 int size = JSObject::kHeaderSize + casted_stub()->length() * kPointerSize; |
| 428 HValue* boilerplate_size = | 418 HValue* boilerplate_size = |
| 429 AddInstruction(new(zone) HInstanceSize(boilerplate)); | 419 AddInstruction(new(zone) HInstanceSize(boilerplate)); |
| 430 HValue* size_in_words = | 420 HValue* size_in_words = Add<HConstant>(size >> kPointerSizeLog2); |
| 431 AddInstruction(new(zone) HConstant(size >> kPointerSizeLog2)); | |
| 432 checker.If<HCompareNumericAndBranch>(boilerplate_size, | 421 checker.If<HCompareNumericAndBranch>(boilerplate_size, |
| 433 size_in_words, Token::EQ); | 422 size_in_words, Token::EQ); |
| 434 checker.Then(); | 423 checker.Then(); |
| 435 | 424 |
| 436 HValue* size_in_bytes = AddInstruction(new(zone) HConstant(size)); | 425 HValue* size_in_bytes = Add<HConstant>(size); |
| 437 HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE; | |
| 438 if (isolate()->heap()->ShouldGloballyPretenure()) { | |
| 439 flags = static_cast<HAllocate::Flags>( | |
| 440 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); | |
| 441 } | |
| 442 | 426 |
| 443 HInstruction* object = AddInstruction(new(zone) | 427 HInstruction* object = Add<HAllocate>(size_in_bytes, HType::JSObject(), |
| 444 HAllocate(context(), size_in_bytes, HType::JSObject(), flags)); | 428 isolate()->heap()->GetPretenureMode(), JS_OBJECT_TYPE); |
| 445 | 429 |
| 446 for (int i = 0; i < size; i += kPointerSize) { | 430 for (int i = 0; i < size; i += kPointerSize) { |
| 447 HObjectAccess access = HObjectAccess::ForJSObjectOffset(i); | 431 HObjectAccess access = HObjectAccess::ForJSObjectOffset(i); |
| 448 AddStore(object, access, AddLoad(boilerplate, access)); | 432 Add<HStoreNamedField>(object, access, |
| 433 Add<HLoadNamedField>(boilerplate, access)); |
| 449 } | 434 } |
| 450 | 435 |
| 451 environment()->Push(object); | 436 environment()->Push(object); |
| 452 checker.ElseDeopt(); | 437 checker.ElseDeopt(); |
| 453 checker.End(); | 438 checker.End(); |
| 454 | 439 |
| 455 return environment()->Pop(); | 440 return environment()->Pop(); |
| 456 } | 441 } |
| 457 | 442 |
| 458 | 443 |
| 459 Handle<Code> FastCloneShallowObjectStub::GenerateCode() { | 444 Handle<Code> FastCloneShallowObjectStub::GenerateCode() { |
| 460 return DoGenerateCode(this); | 445 return DoGenerateCode(this); |
| 461 } | 446 } |
| 462 | 447 |
| 463 | 448 |
| 464 template <> | 449 template <> |
| 465 HValue* CodeStubGraphBuilder<CreateAllocationSiteStub>::BuildCodeStub() { | 450 HValue* CodeStubGraphBuilder<CreateAllocationSiteStub>::BuildCodeStub() { |
| 466 Zone* zone = this->zone(); | 451 HValue* size = Add<HConstant>(AllocationSite::kSize); |
| 467 | 452 HInstruction* object = Add<HAllocate>(size, HType::JSObject(), TENURED, |
| 468 HValue* size = AddInstruction(new(zone) HConstant(AllocationSite::kSize)); | 453 JS_OBJECT_TYPE); |
| 469 HAllocate::Flags flags = HAllocate::DefaultFlags(); | |
| 470 flags = static_cast<HAllocate::Flags>( | |
| 471 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); | |
| 472 HInstruction* object = AddInstruction(new(zone) | |
| 473 HAllocate(context(), size, HType::JSObject(), flags)); | |
| 474 | 454 |
| 475 // Store the map | 455 // Store the map |
| 476 Handle<Map> allocation_site_map(isolate()->heap()->allocation_site_map(), | 456 Handle<Map> allocation_site_map(isolate()->heap()->allocation_site_map(), |
| 477 isolate()); | 457 isolate()); |
| 478 AddStoreMapConstant(object, allocation_site_map); | 458 AddStoreMapConstant(object, allocation_site_map); |
| 479 | 459 |
| 480 // Store the payload (smi elements kind) | 460 // Store the payload (smi elements kind) |
| 481 HValue* initial_elements_kind = AddInstruction(new(zone) HConstant( | 461 HValue* initial_elements_kind = Add<HConstant>(GetInitialFastElementsKind()); |
| 482 GetInitialFastElementsKind())); | |
| 483 Add<HStoreNamedField>(object, | 462 Add<HStoreNamedField>(object, |
| 484 HObjectAccess::ForAllocationSiteTransitionInfo(), | 463 HObjectAccess::ForAllocationSiteTransitionInfo(), |
| 485 initial_elements_kind); | 464 initial_elements_kind); |
| 486 | 465 |
| 487 Add<HLinkObjectInList>(object, HObjectAccess::ForAllocationSiteWeakNext(), | 466 // Link the object to the allocation site list |
| 488 HLinkObjectInList::ALLOCATION_SITE_LIST); | 467 HValue* site_list = Add<HConstant>( |
| 468 ExternalReference::allocation_sites_list_address(isolate())); |
| 469 HValue* site = Add<HLoadNamedField>(site_list, |
| 470 HObjectAccess::ForAllocationSiteList()); |
| 471 HStoreNamedField* store = |
| 472 Add<HStoreNamedField>(object, HObjectAccess::ForAllocationSiteWeakNext(), |
| 473 site); |
| 474 store->SkipWriteBarrier(); |
| 475 Add<HStoreNamedField>(site_list, HObjectAccess::ForAllocationSiteList(), |
| 476 object); |
| 489 | 477 |
| 490 // We use a hammer (SkipWriteBarrier()) to indicate that we know the input | 478 // We use a hammer (SkipWriteBarrier()) to indicate that we know the input |
| 491 // cell is really a Cell, and so no write barrier is needed. | 479 // cell is really a Cell, and so no write barrier is needed. |
| 492 // TODO(mvstanton): Add a debug_code check to verify the input cell is really | 480 // TODO(mvstanton): Add a debug_code check to verify the input cell is really |
| 493 // a cell. (perhaps with a new instruction, HAssert). | 481 // a cell. (perhaps with a new instruction, HAssert). |
| 494 HInstruction* cell = GetParameter(0); | 482 HInstruction* cell = GetParameter(0); |
| 495 HObjectAccess access = HObjectAccess::ForCellValue(); | 483 HObjectAccess access = HObjectAccess::ForCellValue(); |
| 496 HStoreNamedField* store = AddStore(cell, access, object); | 484 store = Add<HStoreNamedField>(cell, access, object); |
| 497 store->SkipWriteBarrier(); | 485 store->SkipWriteBarrier(); |
| 498 return cell; | 486 return cell; |
| 499 } | 487 } |
| 500 | 488 |
| 501 | 489 |
| 502 Handle<Code> CreateAllocationSiteStub::GenerateCode() { | 490 Handle<Code> CreateAllocationSiteStub::GenerateCode() { |
| 503 return DoGenerateCode(this); | 491 return DoGenerateCode(this); |
| 504 } | 492 } |
| 505 | 493 |
| 506 | 494 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 return DoGenerateCode(this); | 571 return DoGenerateCode(this); |
| 584 } | 572 } |
| 585 | 573 |
| 586 HValue* CodeStubGraphBuilderBase::BuildArrayConstructor( | 574 HValue* CodeStubGraphBuilderBase::BuildArrayConstructor( |
| 587 ElementsKind kind, | 575 ElementsKind kind, |
| 588 ContextCheckMode context_mode, | 576 ContextCheckMode context_mode, |
| 589 AllocationSiteOverrideMode override_mode, | 577 AllocationSiteOverrideMode override_mode, |
| 590 ArgumentClass argument_class) { | 578 ArgumentClass argument_class) { |
| 591 HValue* constructor = GetParameter(ArrayConstructorStubBase::kConstructor); | 579 HValue* constructor = GetParameter(ArrayConstructorStubBase::kConstructor); |
| 592 if (context_mode == CONTEXT_CHECK_REQUIRED) { | 580 if (context_mode == CONTEXT_CHECK_REQUIRED) { |
| 593 HInstruction* array_function = BuildGetArrayFunction(context()); | 581 HInstruction* array_function = BuildGetArrayFunction(); |
| 594 ArrayContextChecker checker(this, constructor, array_function); | 582 ArrayContextChecker checker(this, constructor, array_function); |
| 595 } | 583 } |
| 596 | 584 |
| 597 HValue* property_cell = GetParameter(ArrayConstructorStubBase::kPropertyCell); | 585 HValue* property_cell = GetParameter(ArrayConstructorStubBase::kPropertyCell); |
| 598 // Walk through the property cell to the AllocationSite | 586 // Walk through the property cell to the AllocationSite |
| 599 HValue* alloc_site = AddInstruction(new(zone()) HLoadNamedField(property_cell, | 587 HValue* alloc_site = Add<HLoadNamedField>(property_cell, |
| 600 HObjectAccess::ForCellValue())); | 588 HObjectAccess::ForCellValue()); |
| 601 JSArrayBuilder array_builder(this, kind, alloc_site, constructor, | 589 JSArrayBuilder array_builder(this, kind, alloc_site, constructor, |
| 602 override_mode); | 590 override_mode); |
| 603 HValue* result = NULL; | 591 HValue* result = NULL; |
| 604 switch (argument_class) { | 592 switch (argument_class) { |
| 605 case NONE: | 593 case NONE: |
| 606 result = array_builder.AllocateEmptyArray(); | 594 result = array_builder.AllocateEmptyArray(); |
| 607 break; | 595 break; |
| 608 case SINGLE: | 596 case SINGLE: |
| 609 result = BuildArraySingleArgumentConstructor(&array_builder); | 597 result = BuildArraySingleArgumentConstructor(&array_builder); |
| 610 break; | 598 break; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 638 return result; | 626 return result; |
| 639 } | 627 } |
| 640 | 628 |
| 641 | 629 |
| 642 HValue* CodeStubGraphBuilderBase::BuildArraySingleArgumentConstructor( | 630 HValue* CodeStubGraphBuilderBase::BuildArraySingleArgumentConstructor( |
| 643 JSArrayBuilder* array_builder) { | 631 JSArrayBuilder* array_builder) { |
| 644 // Smi check and range check on the input arg. | 632 // Smi check and range check on the input arg. |
| 645 HValue* constant_one = graph()->GetConstant1(); | 633 HValue* constant_one = graph()->GetConstant1(); |
| 646 HValue* constant_zero = graph()->GetConstant0(); | 634 HValue* constant_zero = graph()->GetConstant0(); |
| 647 | 635 |
| 648 HInstruction* elements = AddInstruction( | 636 HInstruction* elements = Add<HArgumentsElements>(false); |
| 649 new(zone()) HArgumentsElements(false)); | |
| 650 HInstruction* argument = AddInstruction( | 637 HInstruction* argument = AddInstruction( |
| 651 new(zone()) HAccessArgumentsAt(elements, constant_one, constant_zero)); | 638 new(zone()) HAccessArgumentsAt(elements, constant_one, constant_zero)); |
| 652 | 639 |
| 653 HConstant* max_alloc_length = | 640 HConstant* max_alloc_length = |
| 654 new(zone()) HConstant(JSObject::kInitialMaxFastElementArray); | 641 Add<HConstant>(JSObject::kInitialMaxFastElementArray); |
| 655 AddInstruction(max_alloc_length); | |
| 656 const int initial_capacity = JSArray::kPreallocatedArrayElements; | 642 const int initial_capacity = JSArray::kPreallocatedArrayElements; |
| 657 HConstant* initial_capacity_node = new(zone()) HConstant(initial_capacity); | 643 HConstant* initial_capacity_node = New<HConstant>(initial_capacity); |
| 658 AddInstruction(initial_capacity_node); | 644 AddInstruction(initial_capacity_node); |
| 659 | 645 |
| 660 HBoundsCheck* checked_arg = Add<HBoundsCheck>(argument, max_alloc_length); | 646 HInstruction* checked_arg = Add<HBoundsCheck>(argument, max_alloc_length); |
| 661 IfBuilder if_builder(this); | 647 IfBuilder if_builder(this); |
| 662 if_builder.If<HCompareNumericAndBranch>(checked_arg, constant_zero, | 648 if_builder.If<HCompareNumericAndBranch>(checked_arg, constant_zero, |
| 663 Token::EQ); | 649 Token::EQ); |
| 664 if_builder.Then(); | 650 if_builder.Then(); |
| 665 Push(initial_capacity_node); // capacity | 651 Push(initial_capacity_node); // capacity |
| 666 Push(constant_zero); // length | 652 Push(constant_zero); // length |
| 667 if_builder.Else(); | 653 if_builder.Else(); |
| 668 Push(checked_arg); // capacity | 654 Push(checked_arg); // capacity |
| 669 Push(checked_arg); // length | 655 Push(checked_arg); // length |
| 670 if_builder.End(); | 656 if_builder.End(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 690 fill_with_hole); | 676 fill_with_hole); |
| 691 HValue* elements = array_builder->GetElementsLocation(); | 677 HValue* elements = array_builder->GetElementsLocation(); |
| 692 ASSERT(elements != NULL); | 678 ASSERT(elements != NULL); |
| 693 | 679 |
| 694 // Now populate the elements correctly. | 680 // Now populate the elements correctly. |
| 695 LoopBuilder builder(this, | 681 LoopBuilder builder(this, |
| 696 context(), | 682 context(), |
| 697 LoopBuilder::kPostIncrement); | 683 LoopBuilder::kPostIncrement); |
| 698 HValue* start = graph()->GetConstant0(); | 684 HValue* start = graph()->GetConstant0(); |
| 699 HValue* key = builder.BeginBody(start, length, Token::LT); | 685 HValue* key = builder.BeginBody(start, length, Token::LT); |
| 700 HInstruction* argument_elements = AddInstruction( | 686 HInstruction* argument_elements = Add<HArgumentsElements>(false); |
| 701 new(zone()) HArgumentsElements(false)); | |
| 702 HInstruction* argument = AddInstruction(new(zone()) HAccessArgumentsAt( | 687 HInstruction* argument = AddInstruction(new(zone()) HAccessArgumentsAt( |
| 703 argument_elements, length, key)); | 688 argument_elements, length, key)); |
| 704 | 689 |
| 705 AddInstruction(new(zone()) HStoreKeyed(elements, key, argument, kind)); | 690 Add<HStoreKeyed>(elements, key, argument, kind); |
| 706 builder.EndBody(); | 691 builder.EndBody(); |
| 707 return new_object; | 692 return new_object; |
| 708 } | 693 } |
| 709 | 694 |
| 710 | 695 |
| 711 template <> | 696 template <> |
| 712 HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() { | 697 HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() { |
| 713 ElementsKind kind = casted_stub()->elements_kind(); | 698 ElementsKind kind = casted_stub()->elements_kind(); |
| 714 ContextCheckMode context_mode = casted_stub()->context_mode(); | 699 ContextCheckMode context_mode = casted_stub()->context_mode(); |
| 715 AllocationSiteOverrideMode override_mode = casted_stub()->override_mode(); | 700 AllocationSiteOverrideMode override_mode = casted_stub()->override_mode(); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 818 | 803 |
| 819 template <> | 804 template <> |
| 820 HValue* CodeStubGraphBuilder<UnaryOpStub>::BuildCodeInitializedStub() { | 805 HValue* CodeStubGraphBuilder<UnaryOpStub>::BuildCodeInitializedStub() { |
| 821 UnaryOpStub* stub = casted_stub(); | 806 UnaryOpStub* stub = casted_stub(); |
| 822 Handle<Type> type = stub->GetType(graph()->isolate()); | 807 Handle<Type> type = stub->GetType(graph()->isolate()); |
| 823 HValue* input = GetParameter(0); | 808 HValue* input = GetParameter(0); |
| 824 | 809 |
| 825 // Prevent unwanted HChange being inserted to ensure that the stub | 810 // Prevent unwanted HChange being inserted to ensure that the stub |
| 826 // deopts on newly encountered types. | 811 // deopts on newly encountered types. |
| 827 if (!type->Maybe(Type::Double())) { | 812 if (!type->Maybe(Type::Double())) { |
| 828 input = AddInstruction(new(zone()) | 813 input = Add<HForceRepresentation>(input, Representation::Smi()); |
| 829 HForceRepresentation(input, Representation::Smi())); | |
| 830 } | 814 } |
| 831 | 815 |
| 832 if (!type->Is(Type::Number())) { | 816 if (!type->Is(Type::Number())) { |
| 833 // If we expect to see other things than Numbers, we will create a generic | 817 // If we expect to see other things than Numbers, we will create a generic |
| 834 // stub, which handles all numbers and calls into the runtime for the rest. | 818 // stub, which handles all numbers and calls into the runtime for the rest. |
| 835 IfBuilder if_number(this); | 819 IfBuilder if_number(this); |
| 836 if_number.If<HIsNumberAndBranch>(input); | 820 if_number.If<HIsNumberAndBranch>(input); |
| 837 if_number.Then(); | 821 if_number.Then(); |
| 838 HInstruction* res = BuildUnaryMathOp(input, type, stub->operation()); | 822 HInstruction* res = BuildUnaryMathOp(input, type, stub->operation()); |
| 839 if_number.Return(AddInstruction(res)); | 823 if_number.Return(AddInstruction(res)); |
| 840 if_number.Else(); | 824 if_number.Else(); |
| 841 HValue* function = AddLoadJSBuiltin(stub->ToJSBuiltin(), context()); | 825 HValue* function = AddLoadJSBuiltin(stub->ToJSBuiltin()); |
| 842 Add<HPushArgument>(GetParameter(0)); | 826 Add<HPushArgument>(GetParameter(0)); |
| 843 HValue* result = Add<HInvokeFunction>(context(), function, 1); | 827 HValue* result = Add<HInvokeFunction>(function, 1); |
| 844 if_number.Return(result); | 828 if_number.Return(result); |
| 845 if_number.End(); | 829 if_number.End(); |
| 846 return graph()->GetConstantUndefined(); | 830 return graph()->GetConstantUndefined(); |
| 847 } | 831 } |
| 848 | 832 |
| 849 return AddInstruction(BuildUnaryMathOp(input, type, stub->operation())); | 833 return AddInstruction(BuildUnaryMathOp(input, type, stub->operation())); |
| 850 } | 834 } |
| 851 | 835 |
| 852 | 836 |
| 853 Handle<Code> UnaryOpStub::GenerateCode() { | 837 Handle<Code> UnaryOpStub::GenerateCode() { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 881 Handle<Object> placeholer_value(Smi::FromInt(0), isolate()); | 865 Handle<Object> placeholer_value(Smi::FromInt(0), isolate()); |
| 882 Handle<PropertyCell> placeholder_cell = | 866 Handle<PropertyCell> placeholder_cell = |
| 883 isolate()->factory()->NewPropertyCell(placeholer_value); | 867 isolate()->factory()->NewPropertyCell(placeholer_value); |
| 884 | 868 |
| 885 HParameter* receiver = GetParameter(0); | 869 HParameter* receiver = GetParameter(0); |
| 886 HParameter* value = GetParameter(2); | 870 HParameter* value = GetParameter(2); |
| 887 | 871 |
| 888 // Check that the map of the global has not changed: use a placeholder map | 872 // Check that the map of the global has not changed: use a placeholder map |
| 889 // that will be replaced later with the global object's map. | 873 // that will be replaced later with the global object's map. |
| 890 Handle<Map> placeholder_map = isolate()->factory()->meta_map(); | 874 Handle<Map> placeholder_map = isolate()->factory()->meta_map(); |
| 891 AddInstruction(HCheckMaps::New( | 875 Add<HCheckMaps>(receiver, placeholder_map, top_info()); |
| 892 receiver, placeholder_map, zone(), top_info())); | |
| 893 | 876 |
| 894 HValue* cell = Add<HConstant>(placeholder_cell, Representation::Tagged()); | 877 HValue* cell = Add<HConstant>(placeholder_cell); |
| 895 HObjectAccess access(HObjectAccess::ForCellPayload(isolate())); | 878 HObjectAccess access(HObjectAccess::ForCellPayload(isolate())); |
| 896 HValue* cell_contents = Add<HLoadNamedField>(cell, access); | 879 HValue* cell_contents = Add<HLoadNamedField>(cell, access); |
| 897 | 880 |
| 898 if (stub->is_constant()) { | 881 if (stub->is_constant()) { |
| 899 IfBuilder builder(this); | 882 IfBuilder builder(this); |
| 900 builder.If<HCompareObjectEqAndBranch>(cell_contents, value); | 883 builder.If<HCompareObjectEqAndBranch>(cell_contents, value); |
| 901 builder.Then(); | 884 builder.Then(); |
| 902 builder.ElseDeopt(); | 885 builder.ElseDeopt(); |
| 903 builder.End(); | 886 builder.End(); |
| 904 } else { | 887 } else { |
| 905 // Load the payload of the global parameter cell. A hole indicates that the | 888 // Load the payload of the global parameter cell. A hole indicates that the |
| 906 // property has been deleted and that the store must be handled by the | 889 // property has been deleted and that the store must be handled by the |
| 907 // runtime. | 890 // runtime. |
| 908 IfBuilder builder(this); | 891 IfBuilder builder(this); |
| 909 HValue* hole_value = Add<HConstant>(hole, Representation::Tagged()); | 892 HValue* hole_value = Add<HConstant>(hole); |
| 910 builder.If<HCompareObjectEqAndBranch>(cell_contents, hole_value); | 893 builder.If<HCompareObjectEqAndBranch>(cell_contents, hole_value); |
| 911 builder.Then(); | 894 builder.Then(); |
| 912 builder.Deopt(); | 895 builder.Deopt(); |
| 913 builder.Else(); | 896 builder.Else(); |
| 914 Add<HStoreNamedField>(cell, access, value); | 897 Add<HStoreNamedField>(cell, access, value); |
| 915 builder.End(); | 898 builder.End(); |
| 916 } | 899 } |
| 917 | 900 |
| 918 return value; | 901 return value; |
| 919 } | 902 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 return value; | 935 return value; |
| 953 } | 936 } |
| 954 | 937 |
| 955 | 938 |
| 956 Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() { | 939 Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() { |
| 957 return DoGenerateCode(this); | 940 return DoGenerateCode(this); |
| 958 } | 941 } |
| 959 | 942 |
| 960 | 943 |
| 961 } } // namespace v8::internal | 944 } } // namespace v8::internal |
| OLD | NEW |