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

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

Issue 3158020: Use Copy-on-write arrays for cached regexp results. (Closed)
Patch Set: Changed comments. Created 10 years, 4 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
OLDNEW
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 5502 matching lines...) Expand 10 before | Expand all | Expand 10 after
5513 __ push(Immediate(node_->pattern())); 5513 __ push(Immediate(node_->pattern()));
5514 // RegExp flags (3). 5514 // RegExp flags (3).
5515 __ push(Immediate(node_->flags())); 5515 __ push(Immediate(node_->flags()));
5516 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 5516 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
5517 if (!boilerplate_.is(eax)) __ mov(boilerplate_, eax); 5517 if (!boilerplate_.is(eax)) __ mov(boilerplate_, eax);
5518 } 5518 }
5519 5519
5520 5520
5521 class DeferredAllocateInNewSpace: public DeferredCode { 5521 class DeferredAllocateInNewSpace: public DeferredCode {
5522 public: 5522 public:
5523 DeferredAllocateInNewSpace(int size, Register target) 5523 DeferredAllocateInNewSpace(int size,
5524 : size_(size), target_(target) { 5524 Register target,
5525 int registers_to_save = 0)
5526 : size_(size), target_(target), registers_to_save_(registers_to_save) {
5525 ASSERT(size >= kPointerSize && size <= Heap::MaxObjectSizeInNewSpace()); 5527 ASSERT(size >= kPointerSize && size <= Heap::MaxObjectSizeInNewSpace());
5528 ASSERT_EQ(0, registers_to_save & target.bit());
5526 set_comment("[ DeferredAllocateInNewSpace"); 5529 set_comment("[ DeferredAllocateInNewSpace");
5527 } 5530 }
5528 void Generate(); 5531 void Generate();
5529 5532
5530 private: 5533 private:
5531 int size_; 5534 int size_;
5532 Register target_; 5535 Register target_;
5536 int registers_to_save_;
5533 }; 5537 };
5534 5538
5535 5539
5536 void DeferredAllocateInNewSpace::Generate() { 5540 void DeferredAllocateInNewSpace::Generate() {
5541 for (int i = 0; i < kNumRegs; i++) {
5542 if (registers_to_save_ & (1 << i)) {
5543 Register save_register = { i };
5544 __ push(save_register);
5545 }
5546 }
5537 __ push(Immediate(Smi::FromInt(size_))); 5547 __ push(Immediate(Smi::FromInt(size_)));
5538 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 5548 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
5539 if (!target_.is(eax)) { 5549 if (!target_.is(eax)) {
5540 __ mov(target_, eax); 5550 __ mov(target_, eax);
5541 } 5551 }
5552 for (int i = kNumRegs - 1; i >= 0; i--) {
5553 if (registers_to_save_ & (1 << i)) {
5554 Register save_register = { i };
5555 __ pop(save_register);
5556 }
5557 }
5542 } 5558 }
5543 5559
5544 5560
5545 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 5561 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
5546 ASSERT(!in_safe_int32_mode()); 5562 ASSERT(!in_safe_int32_mode());
5547 Comment cmnt(masm_, "[ RegExp Literal"); 5563 Comment cmnt(masm_, "[ RegExp Literal");
5548 5564
5549 // Retrieve the literals array and check the allocated entry. Begin 5565 // Retrieve the literals array and check the allocated entry. Begin
5550 // with a writable copy of the function of this activation in a 5566 // with a writable copy of the function of this activation in a
5551 // register. 5567 // register.
(...skipping 1803 matching lines...) Expand 10 before | Expand all | Expand 10 after
7355 __ bind(&slowcase); 7371 __ bind(&slowcase);
7356 __ CallRuntime(Runtime::kRegExpConstructResult, 3); 7372 __ CallRuntime(Runtime::kRegExpConstructResult, 3);
7357 7373
7358 __ bind(&done); 7374 __ bind(&done);
7359 } 7375 }
7360 frame_->Forget(3); 7376 frame_->Forget(3);
7361 frame_->Push(eax); 7377 frame_->Push(eax);
7362 } 7378 }
7363 7379
7364 7380
7381 void CodeGenerator::GenerateRegExpCloneResult(ZoneList<Expression*>* args) {
7382 ASSERT_EQ(1, args->length());
7383
7384 Load(args->at(0));
7385 Result object_result = frame_->Pop();
7386 object_result.ToRegister(eax);
7387 object_result.Unuse();
7388 {
7389 VirtualFrame::SpilledScope spilled_scope;
7390
7391 Label done;
7392
7393 __ test(eax, Immediate(kSmiTagMask));
7394 __ j(zero, &done);
7395
7396 // Load JSRegExpResult map into edx.
7397 // Arguments to this function should be results of calling RegExp exec,
7398 // which is either an unmodified JSRegExpResult or null. Anything not having
7399 // the unmodified JSRegExpResult map is returned unmodified.
7400 // This also ensures that elements are fast.
7401 __ mov(edx, ContextOperand(esi, Context::GLOBAL_INDEX));
7402 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalContextOffset));
7403 __ mov(edx, ContextOperand(edx, Context::REGEXP_RESULT_MAP_INDEX));
7404 __ cmp(edx, FieldOperand(eax, HeapObject::kMapOffset));
7405 __ j(not_equal, &done);
7406
7407 if (FLAG_debug_code) {
Vitaly Repeshko 2010/08/20 13:29:49 Should be checked in arm and x64 versions as well.
Lasse Reichstein 2010/08/23 12:52:11 Done.
7408 // Check that object really has empty properties array, as the map
7409 // should guarantee.
7410 __ cmp(FieldOperand(eax, JSObject::kPropertiesOffset),
7411 Immediate(Factory::empty_fixed_array()));
7412 __ Check(equal, "JSRegExpResult: default map but non-empty properties.");
7413 }
7414
7415 DeferredAllocateInNewSpace* allocate_fallback =
7416 new DeferredAllocateInNewSpace(JSRegExpResult::kSize,
7417 ebx,
7418 edx.bit() | eax.bit());
7419
7420 // All set, copy the contents to a new object.
7421 __ AllocateInNewSpace(JSRegExpResult::kSize,
7422 ebx,
7423 ecx,
7424 no_reg,
7425 allocate_fallback->entry_label(),
7426 TAG_OBJECT);
7427 __ bind(allocate_fallback->exit_label());
7428
7429 // Copy all fields from eax to ebx.
7430 STATIC_ASSERT(JSRegExpResult::kSize % (2 * kPointerSize) == 0);
7431 // There is an even number of fields, so unroll the loop once
7432 // for efficiency.
7433 for (int i = 0; i < JSRegExpResult::kSize; i += 2 * kPointerSize) {
7434 STATIC_ASSERT(JSObject::kMapOffset % (2 * kPointerSize) == 0);
7435 if (i != JSObject::kMapOffset) {
7436 // The map was already loaded into edx.
7437 __ mov(edx, FieldOperand(eax, i));
7438 }
7439 __ mov(ecx, FieldOperand(eax, i + kPointerSize));
7440
7441 STATIC_ASSERT(JSObject::kElementsOffset % (2 * kPointerSize) == 0);
7442 if (i == JSObject::kElementsOffset) {
7443 // If the elements array isn't empty, make it copy-on-write
7444 // before copying it.
7445 Label empty;
7446 __ cmp(Operand(edx), Immediate(Factory::empty_fixed_array()));
7447 __ j(equal, &empty);
7448 ASSERT(!Heap::InNewSpace(Heap::fixed_cow_array_map()));
7449 __ mov(FieldOperand(edx, HeapObject::kMapOffset),
7450 Immediate(Factory::fixed_cow_array_map()));
7451 __ bind(&empty);
7452 }
7453 __ mov(FieldOperand(ebx, i), edx);
7454 __ mov(FieldOperand(ebx, i + kPointerSize), ecx);
7455 }
7456 __ mov(eax, ebx);
7457
7458 __ bind(&done);
7459 }
7460 frame_->Push(eax);
7461 }
7462
7463
7365 class DeferredSearchCache: public DeferredCode { 7464 class DeferredSearchCache: public DeferredCode {
7366 public: 7465 public:
7367 DeferredSearchCache(Register dst, Register cache, Register key) 7466 DeferredSearchCache(Register dst, Register cache, Register key)
7368 : dst_(dst), cache_(cache), key_(key) { 7467 : dst_(dst), cache_(cache), key_(key) {
7369 set_comment("[ DeferredSearchCache"); 7468 set_comment("[ DeferredSearchCache");
7370 } 7469 }
7371 7470
7372 virtual void Generate(); 7471 virtual void Generate();
7373 7472
7374 private: 7473 private:
(...skipping 7031 matching lines...) Expand 10 before | Expand all | Expand 10 after
14406 masm.GetCode(&desc); 14505 masm.GetCode(&desc);
14407 // Call the function from C++. 14506 // Call the function from C++.
14408 return FUNCTION_CAST<MemCopyFunction>(buffer); 14507 return FUNCTION_CAST<MemCopyFunction>(buffer);
14409 } 14508 }
14410 14509
14411 #undef __ 14510 #undef __
14412 14511
14413 } } // namespace v8::internal 14512 } } // namespace v8::internal
14414 14513
14415 #endif // V8_TARGET_ARCH_IA32 14514 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698