Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: src/codegen-ia32.cc

Issue 17203: Periodic merge from bleeding_edge to experimental code generator... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 11 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/codegen-ia32.h ('k') | src/d8.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 cgen->LoadReference(this); 490 cgen->LoadReference(this);
491 } 491 }
492 492
493 493
494 Reference::~Reference() { 494 Reference::~Reference() {
495 cgen_->UnloadReference(this); 495 cgen_->UnloadReference(this);
496 } 496 }
497 497
498 498
499 void CodeGenerator::LoadReference(Reference* ref) { 499 void CodeGenerator::LoadReference(Reference* ref) {
500 // References are loaded from both spilled and unspilled code. Set the
501 // state to unspilled to allow that (and explicitly spill after
502 // construction at the construction sites).
503 bool was_in_spilled_code = in_spilled_code_;
504 in_spilled_code_ = false;
505
500 Comment cmnt(masm_, "[ LoadReference"); 506 Comment cmnt(masm_, "[ LoadReference");
501 Expression* e = ref->expression(); 507 Expression* e = ref->expression();
502 Property* property = e->AsProperty(); 508 Property* property = e->AsProperty();
503 Variable* var = e->AsVariableProxy()->AsVariable(); 509 Variable* var = e->AsVariableProxy()->AsVariable();
504 510
505 if (property != NULL) { 511 if (property != NULL) {
506 // The expression is either a property or a variable proxy that rewrites 512 // The expression is either a property or a variable proxy that rewrites
507 // to a property. 513 // to a property.
508 Load(property->obj()); 514 Load(property->obj());
509 // We use a named reference if the key is a literal symbol, unless it is 515 // We use a named reference if the key is a literal symbol, unless it is
(...skipping 19 matching lines...) Expand all
529 ref->set_type(Reference::NAMED); 535 ref->set_type(Reference::NAMED);
530 } else { 536 } else {
531 ASSERT(var->slot() != NULL); 537 ASSERT(var->slot() != NULL);
532 ref->set_type(Reference::SLOT); 538 ref->set_type(Reference::SLOT);
533 } 539 }
534 } else { 540 } else {
535 // Anything else is a runtime error. 541 // Anything else is a runtime error.
536 Load(e); 542 Load(e);
537 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); 543 frame_->CallRuntime(Runtime::kThrowReferenceError, 1);
538 } 544 }
545
546 in_spilled_code_ = was_in_spilled_code;
539 } 547 }
540 548
541 549
542 void CodeGenerator::UnloadReference(Reference* ref) { 550 void CodeGenerator::UnloadReference(Reference* ref) {
543 // Pop a reference from the stack while preserving TOS. 551 // Pop a reference from the stack while preserving TOS.
544 Comment cmnt(masm_, "[ UnloadReference"); 552 Comment cmnt(masm_, "[ UnloadReference");
545 int size = ref->size(); 553 int size = ref->size();
546 if (size == 1) { 554 if (size == 1) {
547 VirtualFrame::SpilledScope spilled_scope(this); 555 VirtualFrame::SpilledScope spilled_scope(this);
548 frame_->EmitPop(eax); 556 frame_->EmitPop(eax);
(...skipping 2784 matching lines...) Expand 10 before | Expand all | Expand 10 after
3333 3341
3334 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 3342 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
3335 ASSERT(args->length() == 1); 3343 ASSERT(args->length() == 1);
3336 LoadAndSpill(args->at(0)); 3344 LoadAndSpill(args->at(0));
3337 frame_->EmitPop(eax); 3345 frame_->EmitPop(eax);
3338 __ test(eax, Immediate(kSmiTagMask)); 3346 __ test(eax, Immediate(kSmiTagMask));
3339 cc_reg_ = zero; 3347 cc_reg_ = zero;
3340 } 3348 }
3341 3349
3342 3350
3351 void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) {
3352 // Conditionally generate a log call.
3353 // Args:
3354 // 0 (literal string): The type of logging (corresponds to the flags).
3355 // This is used to determine whether or not to generate the log call.
3356 // 1 (string): Format string. Access the string at argument index 2
3357 // with '%2s' (see Logger::LogRuntime for all the formats).
3358 // 2 (array): Arguments to the format string.
3359 ASSERT_EQ(args->length(), 3);
3360 if (ShouldGenerateLog(args->at(0))) {
3361 LoadAndSpill(args->at(1));
3362 LoadAndSpill(args->at(2));
3363 frame_->CallRuntime(Runtime::kLog, 2);
3364 }
3365 // Finally, we're expected to leave a value on the top of the stack.
3366 frame_->EmitPush(Immediate(Factory::undefined_value()));
3367 }
3368
3369
3343 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 3370 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
3344 ASSERT(args->length() == 1); 3371 ASSERT(args->length() == 1);
3345 LoadAndSpill(args->at(0)); 3372 LoadAndSpill(args->at(0));
3346 frame_->EmitPop(eax); 3373 frame_->EmitPop(eax);
3347 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); 3374 __ test(eax, Immediate(kSmiTagMask | 0x80000000));
3348 cc_reg_ = zero; 3375 cc_reg_ = zero;
3349 } 3376 }
3350 3377
3351 3378
3352 // This generates code that performs a charCodeAt() call or returns 3379 // This generates code that performs a charCodeAt() call or returns
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after
4282 bool CodeGenerator::HasValidEntryRegisters() { 4309 bool CodeGenerator::HasValidEntryRegisters() {
4283 return (allocator()->count(eax) - frame()->register_count(eax) == 0) 4310 return (allocator()->count(eax) - frame()->register_count(eax) == 0)
4284 && (allocator()->count(ebx) - frame()->register_count(ebx) == 0) 4311 && (allocator()->count(ebx) - frame()->register_count(ebx) == 0)
4285 && (allocator()->count(ecx) - frame()->register_count(ecx) == 0) 4312 && (allocator()->count(ecx) - frame()->register_count(ecx) == 0)
4286 && (allocator()->count(edx) - frame()->register_count(edx) == 0) 4313 && (allocator()->count(edx) - frame()->register_count(edx) == 0)
4287 && (allocator()->count(edi) - frame()->register_count(edi) == 0); 4314 && (allocator()->count(edi) - frame()->register_count(edi) == 0);
4288 } 4315 }
4289 #endif 4316 #endif
4290 4317
4291 4318
4319 class DeferredReferenceGetKeyedValue: public DeferredCode {
4320 public:
4321 DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global)
4322 : DeferredCode(generator), is_global_(is_global) {
4323 set_comment("[ DeferredReferenceGetKeyedValue");
4324 }
4325
4326 virtual void Generate() {
4327 // The argument are actually passed in edx and on top of the frame.
4328 enter()->Bind();
4329 VirtualFrame::SpilledScope spilled_scope(generator());
4330 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
4331 // Calculate the delta from the IC call instruction to the map
4332 // check cmp instruction in the inlined version. This delta is
4333 // stored in a test(eax, delta) instruction after the call so that
4334 // we can find it in the IC initialization code and patch the cmp
4335 // instruction. This means that we cannot allow test instructions
4336 // after calls to KeyedLoadIC stubs in other places.
4337 int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site());
4338 VirtualFrame* frame = generator()->frame();
4339 if (is_global_) {
4340 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
4341 } else {
4342 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4343 }
4344 __ test(eax, Immediate(-delta_to_patch_site));
4345 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
4346 // The result is result is actually returned in eax.
4347 exit()->Jump();
4348 }
4349
4350 Label* patch_site() { return &patch_site_; }
4351
4352 private:
4353 Label patch_site_;
4354 bool is_global_;
4355 };
4356
4357
4292 #undef __ 4358 #undef __
4293 #define __ masm-> 4359 #define __ masm->
4294 4360
4295 Handle<String> Reference::GetName() { 4361 Handle<String> Reference::GetName() {
4296 ASSERT(type_ == NAMED); 4362 ASSERT(type_ == NAMED);
4297 Property* property = expression_->AsProperty(); 4363 Property* property = expression_->AsProperty();
4298 if (property == NULL) { 4364 if (property == NULL) {
4299 // Global variable reference treated as a named property reference. 4365 // Global variable reference treated as a named property reference.
4300 VariableProxy* proxy = expression_->AsVariableProxy(); 4366 VariableProxy* proxy = expression_->AsVariableProxy();
4301 ASSERT(proxy->AsVariable() != NULL); 4367 ASSERT(proxy->AsVariable() != NULL);
(...skipping 16 matching lines...) Expand all
4318 switch (type_) { 4384 switch (type_) {
4319 case SLOT: { 4385 case SLOT: {
4320 Comment cmnt(masm, "[ Load from Slot"); 4386 Comment cmnt(masm, "[ Load from Slot");
4321 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 4387 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
4322 ASSERT(slot != NULL); 4388 ASSERT(slot != NULL);
4323 cgen_->LoadFromSlot(slot, typeof_state); 4389 cgen_->LoadFromSlot(slot, typeof_state);
4324 break; 4390 break;
4325 } 4391 }
4326 4392
4327 case NAMED: { 4393 case NAMED: {
4328 // TODO(1241834): Make sure that this it is safe to ignore the 4394 // TODO(1241834): Make sure that it is safe to ignore the
4329 // distinction between expressions in a typeof and not in a typeof. If 4395 // distinction between expressions in a typeof and not in a
4330 // there is a chance that reference errors can be thrown below, we 4396 // typeof. If there is a chance that reference errors can be
4331 // must distinguish between the two kinds of loads (typeof expression 4397 // thrown below, we must distinguish between the two kinds of
4332 // loads must not throw a reference error). 4398 // loads (typeof expression loads must not throw a reference
4399 // error).
4333 VirtualFrame::SpilledScope spilled_scope(cgen_); 4400 VirtualFrame::SpilledScope spilled_scope(cgen_);
4334 Comment cmnt(masm, "[ Load from named Property"); 4401 Comment cmnt(masm, "[ Load from named Property");
4335 Handle<String> name(GetName()); 4402 Handle<String> name(GetName());
4403 Variable* var = expression_->AsVariableProxy()->AsVariable();
4336 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 4404 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
4337 // Setup the name register. 4405 // Setup the name register.
4338 __ mov(ecx, name); 4406 __ mov(ecx, name);
4339
4340 Variable* var = expression_->AsVariableProxy()->AsVariable();
4341 if (var != NULL) { 4407 if (var != NULL) {
4342 ASSERT(var->is_global()); 4408 ASSERT(var->is_global());
4343 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); 4409 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
4344 } else { 4410 } else {
4345 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4411 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4346 } 4412 }
4347 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4413 frame->EmitPush(eax); // IC call leaves result in eax, push it out
4348 break; 4414 break;
4349 } 4415 }
4350 4416
4351 case KEYED: { 4417 case KEYED: {
4352 // TODO(1241834): Make sure that this it is safe to ignore the 4418 // TODO(1241834): Make sure that this it is safe to ignore the
4353 // distinction between expressions in a typeof and not in a typeof. 4419 // distinction between expressions in a typeof and not in a typeof.
4354 VirtualFrame::SpilledScope spilled_scope(cgen_); 4420 VirtualFrame::SpilledScope spilled_scope(cgen_);
4355 Comment cmnt(masm, "[ Load from keyed Property"); 4421 Comment cmnt(masm, "[ Load from keyed Property");
4356 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 4422 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
4357
4358 Variable* var = expression_->AsVariableProxy()->AsVariable(); 4423 Variable* var = expression_->AsVariableProxy()->AsVariable();
4359 if (var != NULL) { 4424 bool is_global = var != NULL;
4360 ASSERT(var->is_global()); 4425 ASSERT(!is_global || var->is_global());
4361 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); 4426 // Inline array load code if inside of a loop. We do not know
4427 // the receiver map yet, so we initially generate the code with
4428 // a check against an invalid map. In the inline cache code, we
4429 // patch the map check if appropriate.
4430 if (cgen_->loop_nesting() > 0) {
4431 Comment cmnt(masm, "[ Inlined array index load");
4432 DeferredReferenceGetKeyedValue* deferred =
4433 new DeferredReferenceGetKeyedValue(cgen_, is_global);
4434 // Load receiver and check that it is not a smi (only needed
4435 // if this is not a load from the global context) and that it
4436 // has the expected map.
4437 __ mov(edx, Operand(esp, kPointerSize));
4438 if (!is_global) {
4439 __ test(edx, Immediate(kSmiTagMask));
4440 deferred->enter()->Branch(zero, not_taken);
4441 }
4442 // Initially, use an invalid map. The map is patched in the IC
4443 // initialization code.
4444 __ bind(deferred->patch_site());
4445 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
4446 Immediate(Factory::null_value()));
4447 deferred->enter()->Branch(not_equal, not_taken);
4448 // Load key and check that it is a smi.
4449 __ mov(eax, Operand(esp, 0));
4450 __ test(eax, Immediate(kSmiTagMask));
4451 deferred->enter()->Branch(not_zero, not_taken);
4452 // Shift to get actual index value.
4453 __ sar(eax, kSmiTagSize);
4454 // Get the elements array from the receiver and check that it
4455 // is not a dictionary.
4456 __ mov(edx, FieldOperand(edx, JSObject::kElementsOffset));
4457 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
4458 Immediate(Factory::hash_table_map()));
4459 deferred->enter()->Branch(equal, not_taken);
4460 // Check that key is within bounds.
4461 __ cmp(eax, FieldOperand(edx, Array::kLengthOffset));
4462 deferred->enter()->Branch(above_equal, not_taken);
4463 // Load and check that the result is not the hole.
4464 __ mov(eax,
4465 Operand(edx, eax, times_4, Array::kHeaderSize - kHeapObjectTag));
4466 __ cmp(Operand(eax), Immediate(Factory::the_hole_value()));
4467 deferred->enter()->Branch(equal, not_taken);
4468 __ IncrementCounter(&Counters::keyed_load_inline, 1);
4469 deferred->exit()->Bind();
4362 } else { 4470 } else {
4363 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4471 Comment cmnt(masm, "[ Load from keyed Property");
4472 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
4473 if (is_global) {
4474 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
4475 } else {
4476 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4477 }
4478 // Make sure that we do not have a test instruction after the
4479 // call. A test instruction after the call is used to
4480 // indicate that we have generated an inline version of the
4481 // keyed load. The explicit nop instruction is here because
4482 // the push that follows might be peep-hole optimized away.
4483 __ nop();
4364 } 4484 }
4365 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4485 frame->EmitPush(eax); // IC call leaves result in eax, push it out
4366 break; 4486 break;
4367 } 4487 }
4368 4488
4369 default: 4489 default:
4370 UNREACHABLE(); 4490 UNREACHABLE();
4371 } 4491 }
4372 } 4492 }
4373 4493
(...skipping 1450 matching lines...) Expand 10 before | Expand all | Expand 10 after
5824 5944
5825 // Slow-case: Go through the JavaScript implementation. 5945 // Slow-case: Go through the JavaScript implementation.
5826 __ bind(&slow); 5946 __ bind(&slow);
5827 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5947 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5828 } 5948 }
5829 5949
5830 5950
5831 #undef __ 5951 #undef __
5832 5952
5833 } } // namespace v8::internal 5953 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-ia32.h ('k') | src/d8.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698