diff -crBN mozilla-central/layout/style/Makefile.in mozilla-central-pSMT/layout/style/Makefile.in
*** mozilla-central/layout/style/Makefile.in	Wed Oct  7 13:16:57 2009
--- mozilla-central-pSMT/layout/style/Makefile.in	Wed Oct  7 13:16:12 2009
***************
*** 165,170 ****
--- 165,171 ----
  		nsStyleStruct.cpp \
  		nsStyleTransformMatrix.cpp \
  		nsStyleUtil.cpp \
+ 		SelectorThread.cpp \
  		$(NULL)
  
  FORCE_STATIC_LIB = 1
diff -crBN mozilla-central/layout/style/SelectorThread.cpp mozilla-central-pSMT/layout/style/SelectorThread.cpp
*** mozilla-central/layout/style/SelectorThread.cpp	Wed Dec 31 16:00:00 1969
--- mozilla-central-pSMT/layout/style/SelectorThread.cpp	Tue Aug 25 15:14:35 2009
***************
*** 0 ****
--- 1,601 ----
+ /*
+  *  SelectorThread.cpp
+  *  shell
+  *
+  *  Created by Carmen Badea on 07/15/2009.
+  *  Copyright 2009 Intel Corporation. All rights reserved.
+  *
+  */
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <windows.h>
+ #include "SelectorThread.h"
+ #include "nsICSSStyleRule.h"
+ #include "nsIStyleRuleProcessor.h"
+ #include "nsAttrValue.h"
+ 
+ 
+ 	static FILE *f = NULL;
+     static pthread_attr_t attr;
+ 	static bool attr_inited = false;
+ 	//static bool test = false;
+ 	
+ 	
+ 
+ /*
+ AncestorData::AncestorData(RuleProcessorData* _ancestor)
+ {
+ 	ancestor = _ancestor;
+ 	next = NULL;
+ };
+ 
+ AncestorList::AncestorList()
+ {
+ 	head = tail = NULL;
+ 	len = 0;
+ }
+ 
+ bool AncestorList::isEmpty()
+ {
+ 	return (len == 0);
+ }
+ 
+ int AncestorList::getLength()
+ {
+ 	return len;
+ }
+ void AncestorList::add(AncestorData* ancestor)
+ {
+ 	if (head == NULL)
+ 	{
+ 		head = tail = ancestor;
+ 	}
+ 	else
+ 	{
+ 		ancestor->next = NULL;
+ 		tail->next = ancestor;
+ 	}
+ 	len++;
+ }
+ 
+ AncestorData* AncestorList::get()
+ {
+ 	AncestorData* temp;
+ 
+ 	if (head == NULL) 
+ 	{
+ 		return NULL;
+ 	}
+ 	else
+ 	{
+ 		temp = head;
+ 		head = head->next;
+ 		len--;
+ 		return temp;
+ 	}
+ }
+ 
+ */
+ 
+ ThreadData::ThreadData(nsCSSSelector* _selector, RuleProcessorData* _ancestor, PRBool _aForStyling, int _index, int _currentAIndex, int _startAIndex, int _endAIndex)
+ {
+ 	selector = _selector;
+ 	ancestor = _ancestor;
+ 	forStyling = _aForStyling;
+ 	index = _index;
+ 	currentAIndex = _currentAIndex;
+ 	startAIndex = _startAIndex;
+ 	endAIndex = _endAIndex;
+ };
+ 
+ ThreadResult::ThreadResult(int _index, PRBool _result)
+ {
+ 	index = _index;
+ 	result= _result;
+ };
+ 
+ SharedData::SharedData()
+ {
+ 	found = PR_FALSE;
+ 	tSleep = false;
+ 	foundIndex = -1;
+ 	WaitForThreads = 0;
+ 	availableAncestorIndex = -1;
+ 	ancestors = (RuleProcessorData**)malloc(NUM_ANCESTORS * sizeof(RuleProcessorData*));
+ 	for (int i = 0; i < NUM_THREADS; i++)
+ 	{
+ 		//condVars[i] = new CondVar();
+ 		sems[i] = new MySemaphore();
+ 	}
+ 	//mainCondVar = new CondVar();
+ 	mainSem = new MySemaphore();
+ 	mainLock = new Lock();
+ }
+ 
+ void SharedData::wipe()
+ {
+ 	tSleep = false;
+ 	found = PR_FALSE;
+ 	foundIndex = -1;
+ 	WaitForThreads = 0;
+ }
+ /*
+ bool SharedData::ancestorAvailable()
+ {
+ 	return (processedAncestorIndex < availableAncestorIndex);
+ }
+ void SharedData::reallocAncestors(int n)
+ {
+ 	ancestors = (RuleProcessorData**)realloc(ancestors, n * sizeof(RuleProcessorData*));
+ }
+ */
+ //------------------------------------------------------------------------------------------------------------
+ SelectorMainThread::SelectorMainThread(ThreadData** threadsData, FILE *_f,  nsCSSSelector* _initialSelector, RuleProcessorData* _initialPrevData)
+ {
+ 	initialSelector = _initialSelector;
+ 	initialPrevData = _initialPrevData;
+ 	threads = new SelectorThread[NUM_THREADS];
+ 
+ 	if (f == NULL)
+ 	{
+ 		f = _f;
+ 	}
+ 	if (f == NULL)
+     {
+         f = fopen("traceOutput.txt", "a");
+     }
+ 	sharedData = new SharedData();
+ 	
+ 	for (int i = 0; i< NUM_THREADS; i++)
+ 	{
+ 	  threads[i].start(threadsData[i], sharedData);
+ 	}
+ 
+ }
+ 
+ SharedData* SelectorMainThread::startOrWakeup(int mode, int _availableAncestorIndex, RuleProcessorData** _ancestors, FILE* _f, nsCSSSelector* _initialSelector)
+ {
+ 	int i, j, chunk_size;
+ 	
+ 	// update sharedData with the current ancestors array and the current #ancestors
+ 	sharedData->ancestors = _ancestors;
+ 	sharedData->availableAncestorIndex = _availableAncestorIndex - 1;
+ 	
+ 	//compute current chunk size
+ 	chunk_size = floor((_availableAncestorIndex/NUM_THREADS) + 0.5);
+ 
+ 	if (chunk_size < DEFAULT_CHUNK_SIZE)
+ 	{
+ 		chunk_size = DEFAULT_CHUNK_SIZE;
+ 	}
+ 
+ 	if (mode == 1) // Wakeup()
+ 	{
+ #ifdef C_DEBUG
+ 		f = _f;
+ #endif
+ 		//wipe sharedData from the previous SMT call
+ 		sharedData->wipe();
+ 
+ 		//wipe out the thread data from the previous SMT call
+ 		for (i = 0; i < NUM_THREADS; i++)
+ 		{
+ 			threads[i].tData->selector = _initialSelector;
+ 			//threads[i].tData->currentAIndex = -1;
+ 			//threads[i].tData->ancestor = NULL;
+ 		}	
+ 	}
+ 
+ 
+ 	for (i = 0; (i < NUM_THREADS) && (i * chunk_size < sharedData->availableAncestorIndex); i++)
+ 	{
+ 		(threads[i].tData)->startAIndex = i * chunk_size;
+ 		(threads[i].tData)->endAIndex = (i + 1) * chunk_size - 1;
+ 	}
+ #ifdef C_DEBUG1
+ 		if (f == NULL)
+ 		{
+ 			f = fopen("traceOutput.txt", "a");
+ 		}
+ 		if (mode == 0)
+ 		{
+ 			fprintf(f,  "mainThread->start(): #ancestors = %d, #threads available = %d, #working threads = %d, chunk_size = %d, WFT = %d\n\n", _availableAncestorIndex, NUM_THREADS, i, chunk_size, sharedData->WaitForThreads);
+ 			fflush(f);
+ 		}
+ 		else
+ 		{
+ 			fprintf(f,  "mainThread->wakeup(): #ancestors = %d, #threads available = %d, #working threads = %d, chunk_size = %d, WFT = %d\n\n", _availableAncestorIndex, NUM_THREADS, i, chunk_size, sharedData->WaitForThreads);
+ 			fflush(f);
+ 		}
+ #endif
+ 
+ 	(threads[i-1].tData)->endAIndex = _availableAncestorIndex - 1;
+ 
+ #ifdef C_DEBUG
+ 	if (mode == 0)
+ 	{
+ 		fprintf(f,  "mainThread->start(): #ancestors = %d, #threads available = %d, #working threads = %d, chunk_size = %d, WFT = %d\n", _availableAncestorIndex, NUM_THREADS, i, chunk_size, sharedData->WaitForThreads);
+ 		fflush(f);
+ 	}
+ 	else
+ 	{
+ 		fprintf(f,  "mainThread->wakeup(): #ancestors = %d, #threads available = %d, #working threads = %d, chunk_size = %d, WFT = %d\n", _availableAncestorIndex, NUM_THREADS, i, chunk_size, sharedData->WaitForThreads);
+ 		fflush(f);
+ 	}
+ #endif
+ 	sharedData->WaitForThreads = i;
+ 
+ #ifdef C_DEBUG1
+ 
+ 		fprintf(f, "mode = %d, &sharedData = %d, sharedData->WaitForThreads = %d, i = %d\n\n\n", mode, sharedData, sharedData->WaitForThreads, i);
+ 		fflush(f);
+ #endif
+ 
+ 	for (int j = 0; j < i; j++)
+ 	{
+ 		sharedData->sems[j]->post();
+ #ifdef C_DEBUG
+ 	if (mode == 0)
+ 	{
+ 		fprintf(f,  "mainThread->start(): just signalled thread #%d to wake up.\n", j);
+ 	}
+ 	else
+ 	{
+ 		fprintf(f,  "mainThread->wakeup(): just signalled thread #%d to wake up.\n", j);
+ 	}
+ #endif
+ 	}
+ 
+ 	sharedData->mainSem->wait();
+ 
+ /*	
+ 	if (sharedData->WaitForThreads > 0)
+ 	{
+ #ifdef C_DEBUG
+ 		if (mode == 0)
+ 		{
+ 			fprintf(f,  "mainThread->start(): WaitForThreads = %d, going to sleep...\n", sharedData->WaitForThreads);
+ 		}
+ 		else
+ 		{
+ 			fprintf(f,  "mainThread->wakeup(): WaitForThreads = %d, going to sleep...\n", sharedData->WaitForThreads);
+ 		}
+ #endif
+ 		mainSem->wait();
+ #ifdef C_DEBUG
+ 		if (mode == 0)
+ 		{
+ 			fprintf(f,  "mainThread->start(): Just woke up, WaitForThreads = %d, returning to main()...\n", sharedData->WaitForThreads);
+ 		}
+ 		else
+ 		{
+ 			fprintf(f,  "mainThread->wakeup(): Just woke up, WaitForThreads = %d, returning to main()...\n", sharedData->WaitForThreads);
+ 		}
+ #endif
+ 	}
+ */
+ 	return sharedData;
+ }
+ 
+ /*
+ 
+ SharedData* SelectorMainThread::wakeup(int _availableAncestorIndex, RuleProcessorData** _ancestors, nsCSSSelector* _initialSelector, RuleProcessorData* _initialPrevData, FILE* _f)
+ {
+ 	RuleProcessorData *tempData = _initialPrevData, *secondData;
+ 	sharedData->ancestors = _ancestors;
+ 	sharedData->availableAncestorIndex = _availableAncestorIndex -1;
+ 
+ 
+ 
+ #ifdef C_DEBUG
+ 	fprintf(f, "MainThread->wakeup(), before wiping sharedData: availableAncestorIndex = %d, processedAncestorIndex = %d\n", sharedData->availableAncestorIndex, sharedData->processedAncestorIndex);
+ #endif
+ 
+ 	return sharedData;
+ 	
+ }
+ */
+ /*
+ int SelectorMainThread::terminate()
+ {
+ 	int i, index;
+ 	void *status;
+ 	long rc;
+ 
+ 	if (f == NULL)
+     {
+         f = fopen("traceOutput.txt", "a");
+     }
+ #ifdef C_DEBUG
+ 	fprintf(f, "beginning mainThread->terminate()\n");
+ #endif
+ 
+ 	pthread_attr_destroy(&attr);
+ 	for ( i = 0; i < NUM_THREADS; i++)
+ 	{
+ 		index = threads[i].getIndex();
+ 		rc = pthread_join(threads[i].m_pid, &status);
+ 		if (rc) {
+ 			fprintf(f, "ERROR; return code from pthread_join() is %d\n", rc);
+ 			exit(-1);
+ 		}
+ 
+ #ifdef C_DEBUG
+ 		fprintf(f, "SelectorMainThread: completed join with thread %d\n", threads[i].getIndex());
+ 		delete status;
+ #endif
+ 	} // end <join> for
+ #ifdef C_DEBUG
+    	fprintf(f, "finished all joins; found = %d; foundIndex = %d; numAncestors = %d\n", sharedData->found, sharedData->foundIndex, ++sharedData->availableAncestorIndex);
+ #endif
+ 
+ 	return 0;
+ }
+ 
+ */
+ SelectorMainThread::~SelectorMainThread()
+ {
+ 	delete [] threads;
+ 	delete sharedData;
+ }
+ 
+ 
+ //------------------------------------------------------------------------------------------------------------
+ 
+ static void *threadLauncher(void *t) 
+ {	
+ 	if (f == NULL)
+       {
+           f = fopen("traceOutput.txt", "a");
+       }
+ /*
+ #ifdef C_DEBUG
+ 	fprintf(f, " thread #%d -> threadLauncher(), before thread run(), &tData = %d, processing ancestor# %d\n", ((SelectorThread *)t)->getIndex(), ((SelectorThread *)t)->tData, ((SelectorThread *)t)->tData->currentAIndex);
+ #endif
+ 	*/
+ 	return (void *)(((SelectorThread *)t)->run());
+ 	/*
+ #ifdef C_DEBUG
+ 	fprintf(f, " thread #%d -> threadLauncher(), after thread run(), &tData = %d\n", ((SelectorThread *)t)->getIndex(), ((SelectorThread *)t)->tData);
+ #endif
+ */
+ 	//pthread_exit(NULL);
+ 	//return NULL;
+ }
+ 
+ 
+ int SelectorThread::start(ThreadData* _tData, SharedData* _sharedData)
+ {
+ 	if (!attr_inited)
+ 	{
+ 		pthread_attr_init(&attr);
+ 		pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ 		attr_inited = true;
+ 	}
+ 	tData = _tData;
+ 	sharedData = _sharedData;
+ 	if (f == NULL)
+       {
+           f = fopen("traceOutput.txt", "a");
+       }
+ 
+ #ifdef C_DEBUG
+ 	fprintf(f, " thread #%d -> start(), BEFORE thread creation\n", tData->index);
+ #endif	
+ 	int ret = pthread_create(&m_pid, &attr, &threadLauncher, (void *)this);
+ #ifdef C_DEBUG
+ 	fprintf(f, " thread #%d -> start(), AFTER thread creation\n", tData->index);
+ #endif
+ 	return 0;
+ 	
+ }
+ void *SelectorThread::run()
+ {
+ 	PRBool result = PR_FALSE;
+ 	PRBool aForStyling = tData->forStyling;
+ 	int i;
+ 	int index = this->getIndex();
+ 
+ #ifdef C_DEBUG
+ 	if (f == NULL)
+       {
+           f = fopen("traceOutput.txt", "a");
+       }
+ #endif
+ 
+ 	while (true)
+ 	{
+ 		sharedData->sems[index]->wait();
+ #ifdef C_DEBUG
+ 		fprintf(f,  "thread #%d->run(): just woke up, WaitForThreads = %d, startAIndex = %d, endAIndex = %d\n", this->getIndex(), sharedData->WaitForThreads, tData->startAIndex, tData->endAIndex);
+ 		fflush(f);
+ #endif
+ 		
+ 		for (i = tData->startAIndex; i <= tData->endAIndex; i++)
+ 		{
+ 			
+ 			//if  (i < 0) break;
+ 			if ((sharedData->found) && (sharedData->foundIndex < i)) break;
+ 			tData->ancestor = sharedData->ancestors[i];
+ 			//tData->currentAIndex = i;
+ 
+ 			result = parallelSelectorMatches(aForStyling);
+ 			if (result)
+ 			{
+ 				sharedData->mainLock->acquire();
+ 				if (!sharedData->found)
+ 				{
+ 					sharedData->found = true;
+ 					sharedData->foundIndex = i;
+ 				}
+ 				else
+ 				{
+ 					if (i < sharedData->foundIndex)
+ 					{
+ 						sharedData->foundIndex = i;
+ 					}
+ 					//else, there's already an earlier match, so this match is irrelevant
+ 				}					
+ #ifdef C_DEBUG	
+ 	fprintf(f, "thread #%d->run() => *found* match for ancestor %d so it's time for everyone to sleep\n", this->getIndex(), i);
+ #endif
+ 				sharedData->mainLock->release();
+ 				break;
+ 			}
+ #ifdef C_DEBUG	
+ 	fprintf(f, "thread #%d->run() => match not found for ancestor %d, loop again;\n", this->getIndex(), i);
+ #endif
+ 		}
+ 
+ 		sharedData->mainLock->acquire();
+ 
+ 		sharedData->WaitForThreads--;
+ 		if (sharedData->WaitForThreads == 0)
+ 		{
+ #ifdef C_DEBUG
+ 				fprintf(f, "thread #%d->run(): WaitForThreads = %d, everyone's gone to sleep...\n", this->getIndex(), sharedData->WaitForThreads);
+ #endif
+ 			sharedData->mainSem->post();
+ 		}
+ 		sharedData->mainLock->release();
+ 	}
+ 
+ 	return NULL;
+ }
+ 
+ PRBool SelectorThread::parallelSelectorMatches(PRBool aForStyling)
+ {
+ 	//CB->trimmed version of SelectorMatches, designed especially for parallel selector matching
+ 
+ 	nsCSSSelector* aSelector = tData->selector;
+ 	RuleProcessorData* data = tData->ancestor;
+ /*
+ 	if (f == NULL)
+       {
+           f = fopen("traceOutput.txt", "a");
+       }
+ 
+ #ifdef C_DEBUG	
+ 	fprintf(f, "in PSM: thread #%d, processing ancestor %d, &ancestor = %d\n", this->getIndex(), this->getAncestorIndex(), data);
+ #endif
+ */
+ 	
+ /*ORIGINAL
+ 	if ((kNameSpaceID_Unknown != aSelector->mNameSpace &&
+            data.mNameSpaceID != aSelector->mNameSpace) ||
+            (aSelector->mTag && aSelector->mTag != data.mContentTag)) {
+     // optimization : bail out early if we can
+ 	return PR_FALSE;
+ */
+ 
+ 	if ((kNameSpaceID_Unknown != aSelector->mNameSpace &&
+            data->mNameSpaceID != aSelector->mNameSpace) ||
+            (aSelector->mTag && aSelector->mTag != data->mContentTag)) {
+     // optimization : bail out early if we can
+ 		return PR_FALSE;
+ 	}
+ 	
+ 	PRBool result = PR_TRUE;
+ 	const PRBool setNodeFlags = aForStyling;
+ 
+ 
+ 	nsAtomList* IDList = aSelector->mIDList;
+ 	if (result && IDList) 
+ 	{
+ 		// test for ID match
+ 		result = PR_FALSE;
+ 
+ 
+ 	/*not necessary since aAttibute is NULL for parallel selector matching
+ 		if (aAttribute && aAttribute == data.mContent->GetIDAttributeName()) {
+ 			result = PR_TRUE;
+ 			if (aDependence)
+ 			*aDependence = PR_TRUE;
+ 		}
+     else*/
+ 
+ 		if (nsnull != data->mContentID) 
+ 		{
+ 			// case sensitivity: bug 93371
+ 			const PRBool isCaseSensitive =
+ 			data->mCompatMode != eCompatibility_NavQuirks;
+ 			result = PR_TRUE;
+ 
+ 			if (isCaseSensitive) 
+ 			{
+ 				do 
+ 				{
+ 					if (IDList->mAtom != data->mContentID) 
+ 					{
+ 						result = PR_FALSE;
+ 						break;
+ 					}
+ 					IDList = IDList->mNext;
+ 				} while (IDList);
+ 			} 
+ 			else 
+ 			{
+ 				const char* id1Str;
+ 				data->mContentID->GetUTF8String(&id1Str);
+ 				nsDependentCString id1(id1Str);
+ 				do 
+ 				{
+ 					const char* id2Str;
+ 					IDList->mAtom->GetUTF8String(&id2Str);
+ 					if (!id1.Equals(id2Str, nsCaseInsensitiveCStringComparator())) 
+ 					{
+ 						result = PR_FALSE;
+ 						break;
+ 					}
+ 					IDList = IDList->mNext;
+ 				} while (IDList);
+ 			}
+ 		}
+ 	}
+ 
+ 
+    
+   if (result && aSelector->mClassList) 
+   {
+   
+     // test for class match - not necessary since aAttribute = NULL for parallel selector matching
+ 	/*
+     if (aAttribute && aAttribute == data.mContent->GetClassAttributeName()) {
+       result = PR_TRUE;
+       if (aDependence)
+         *aDependence = PR_TRUE;
+     }
+ 
+     else {*/
+ 
+       // case sensitivity: bug 93371
+       const PRBool isCaseSensitive =
+         data->mCompatMode != eCompatibility_NavQuirks;
+ 
+       nsAtomList* classList = aSelector->mClassList;
+       const nsAttrValue *elementClasses = data->mClasses;
+       while (nsnull != classList) 
+ 	  {
+         if (!(elementClasses && elementClasses->Contains(classList->mAtom, isCaseSensitive ? eCaseMatters : eIgnoreCase))) 
+ 		{
+           result = PR_FALSE;
+           break;
+         }
+         classList = classList->mNext;
+       }
+   }
+ 	return result;
+ }
+ 
+ 
+ 
+ int SelectorThread::getIndex()
+ {
+ 	return tData->index;
+ }
+ 
+ int SelectorThread::getAncestorIndex()
+ {
+ 	return tData->currentAIndex;
+ }
+ 
diff -crBN mozilla-central/layout/style/SelectorThread.h mozilla-central-pSMT/layout/style/SelectorThread.h
*** mozilla-central/layout/style/SelectorThread.h	Wed Dec 31 16:00:00 1969
--- mozilla-central-pSMT/layout/style/SelectorThread.h	Tue Aug 25 16:20:29 2009
***************
*** 0 ****
--- 1,216 ----
+ /*
+  *  SelectorThread.h
+  *  shell
+  *
+  *  Created by Carmen Badea on 07/15/2009.
+  *  Copyright 2009 Intel Corporation. All rights reserved.
+  *
+  */
+ 
+ #ifndef __selectorthread_h__
+ #define __selectorthread_h__
+ 
+ 
+ #define PARALLEL_SELECTOR
+ //#define C_DEBUG1
+ #include <pthread.h>
+ #include <sched.h> 
+ #include <semaphore.h>
+ #if defined(DARWIN)
+ #include <libkern/OSAtomic.h>
+ #endif
+ 
+ //#include "plarena.h"
+ #include "pldhash.h"
+ #include "nsINameSpaceManager.h"
+ 
+ #define NUM_THREADS 2 // we'll use 4 thread for now for parallel selector matching
+ #define DEFAULT_CHUNK_SIZE 14
+ #define TEST_ANCESTORS 128
+ #define NUM_ANCESTORS 128
+ 
+ struct RuleProcessorData;
+ struct nsCSSSelector;
+ class CondVar;
+ class Lock;
+ class MySemaphore;
+ 
+ struct ThreadData {
+ public:
+ 	nsCSSSelector* selector;
+ 	RuleProcessorData* ancestor;
+ 	PRBool forStyling;
+ 	int index;// thread index
+ 	int startAIndex; // where the chunk assigned to this thread starts
+ 	int endAIndex; // where the chunk assigned to this thread ends
+ 	int currentAIndex; // index of ancestor currently being processed
+ 
+ 	ThreadData(nsCSSSelector*, RuleProcessorData*, PRBool, int, int, int, int);
+ };
+ 
+ struct ThreadResult {
+ public:
+ 	int index; //index of ancestor currently being processed by the thread returning this ThreadResult object
+ 	PRBool result; // parallel selector matching result for the current thread w/ the current ancestor
+ 
+ 	ThreadResult(int, PRBool);
+ };
+ 
+ struct SharedData {
+ public:
+ 	int chunk_size;
+ 	PRBool found; // has a match been found?
+ 	bool tSleep; // becomes true when the threads need to go to sleep, i.e. a match has been found
+ 	int foundIndex;// if (found), then this is the index of the ancestor that matched
+ 	int availableAncestorIndex; // the index of the last added ancestor to the array of ancestors
+ 	RuleProcessorData** ancestors; // all ancestors available fro this selector (currently handling the case where there is one selector ONLY)
+ 	volatile int WaitForThreads; // keeps track of how many threads that need to sleep are still alive
+ 	//CondVar* condVars[NUM_THREADS]; // used to put to sleep/wake up each worker thread
+ 	//CondVar* mainCondVar; // used to put to sleep/wake up each worker thread
+ 	/*
+ 	pthread_mutex_t t_mutex;// handles synchronized thread access to this shared data 
+ 	//pthread_mutex_t main_mutex;
+ 	pthread_cond_t cv; // handles thread going to sleep / waking up
+ 	pthread_cond_t main_cv;
+ 	*/
+ 	MySemaphore* sems[NUM_THREADS];
+ 	MySemaphore* mainSem;
+ 	Lock* mainLock;
+ 	SharedData();
+ 	void wipe();
+ 	//bool ancestorAvailable();
+ 	//void SharedData::reallocAncestors(int);
+ };
+ class SelectorThread {
+ public:
+ 	SelectorThread(){ tData = NULL; sharedData = NULL;}
+ 	int start(ThreadData* tData, SharedData* sharedData);
+ 	void *run();
+ 	PRBool parallelSelectorMatches(PRBool aForStyling);
+ 	int getIndex(); // returns this thread's index
+ 	int getAncestorIndex(); // returns the index of the ancestor currently being processed by this thread
+ public:
+     ThreadData* tData; 	
+ 	SharedData* sharedData;
+ 	pthread_t m_pid;
+ };
+ 
+ class SelectorMainThread {
+ public:
+ 	SelectorMainThread(ThreadData**, FILE*, nsCSSSelector*, RuleProcessorData*);
+ 	~SelectorMainThread();
+ 	SharedData* startOrWakeup(int, int, RuleProcessorData**, FILE*, nsCSSSelector*);
+ 	int terminate();
+ public:
+ 	SelectorThread* threads;
+ 	SharedData* sharedData;
+ 	nsCSSSelector* initialSelector;
+ 	RuleProcessorData* initialPrevData;
+ };
+ 
+ 
+ class Lock {
+ 	friend class CondVar;
+ public:
+ 	Lock() {
+ 		pthread_mutex_init(&m_lock, NULL);
+ 	};
+ 
+ 	inline void acquire() {
+ 		pthread_mutex_lock(&m_lock);
+ 	};
+ 	
+ 	inline void release() {
+ 		pthread_mutex_unlock(&m_lock);
+ 	};
+ 	
+ 	~Lock() {
+ 		pthread_mutex_destroy(&m_lock);
+ 	};
+ protected:
+ 	pthread_mutex_t m_lock;
+ };
+ 
+ class CondVar {
+ public:
+ 	CondVar() {
+ 		m_lock = new Lock();
+ 		pthread_cond_init(&m_cond, NULL);
+ 	};
+ 	
+ 	inline void acquire() {
+ 		m_lock->acquire();
+ 	};
+ 	
+ 	inline void release() {
+ 		m_lock->release();
+ 	};
+ 	
+ 	inline void wait() {
+ 		pthread_cond_wait(&m_cond, &m_lock->m_lock);
+ 	};
+ 	
+ 	inline void notify() {
+ 		pthread_cond_signal(&m_cond);
+ 	};
+ 	
+ 	~CondVar() {
+ 		delete m_lock;
+ 		pthread_cond_destroy(&m_cond);
+ 	};
+ protected:
+ 	pthread_cond_t m_cond;
+ 	Lock *m_lock;
+ };
+ 
+ class MySemaphore
+ {
+ public:
+ 	MySemaphore()
+ 	{
+ 		sem_init(&semaphore, 0, 0);
+ 	};
+ 	inline void wait()
+ 	{
+ 		sem_wait(&semaphore);
+ 	};
+ 	inline void post()
+ 	{
+ 		sem_post(&semaphore);
+ 	};
+ 	inline int getValue()
+ 	{
+ 		int val;
+ 		sem_getvalue(&semaphore, &val);
+ 		return val;
+ 	};
+ protected:
+ 	sem_t semaphore;
+ };
+ 
+ /* 
+ struct AncestorData {
+ public:
+ 	RuleProcessorData* ancestor;
+ 	AncestorData *next;
+ 
+ 	AncestorData(RuleProcessorData*);
+ };
+ 
+ class AncestorList {
+ public:
+ 	AncestorList();
+ 	~AncestorList();
+ 	void add(AncestorData*);
+ 	AncestorData* get();
+ 	bool isEmpty();
+ 	int getLength();
+ 
+ 	int len;
+ 	AncestorData* head;
+ 	AncestorData* tail;
+ 
+ };
+ 
+ */
+ #endif
diff -crBN mozilla-central/layout/style/nsCSSRuleProcessor.cpp mozilla-central-pSMT/layout/style/nsCSSRuleProcessor.cpp
*** mozilla-central/layout/style/nsCSSRuleProcessor.cpp	Tue Aug 11 15:31:52 2009
--- mozilla-central-pSMT/layout/style/nsCSSRuleProcessor.cpp	Wed Oct  7 13:22:51 2009
***************
*** 46,51 ****
--- 46,52 ----
   */
  
  #include "nsCSSRuleProcessor.h"
+ #define CUSTOM_SMT
  #define PL_ARENA_CONST_ALIGN_MASK 7
  #define NS_RULEHASH_ARENA_BLOCK_SIZE (256)
  #include "plarena.h"
***************
*** 84,89 ****
--- 85,97 ----
  #include "nsIPrincipal.h"
  #include "nsStyleSet.h"
  
+ #ifdef CUSTOM_SMT
+ #include "SelectorThread.h"
+ 
+ #ifdef PARALLEL_SELECTOR
+ #include <pthread.h>
+ #endif
+ #endif
  
  #define VISITED_PSEUDO_PREF "layout.css.visited_links_enabled"
  
***************
*** 92,97 ****
--- 100,117 ----
  static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
  static nsTArray< nsCOMPtr<nsIAtom> >* sSystemMetrics = 0;
  
+ #ifdef CUSTOM_SMT
+ #ifdef PARALLEL_SELECTOR
+ static FILE *f = NULL;
+ static int m, threadid = 0;
+ static bool threads_created = false;
+ static int threads_created2 = 0;
+ static ThreadData* tData[NUM_THREADS];
+ static SelectorMainThread* mainThread;	
+ static RuleProcessorData** tempAncestors = (RuleProcessorData**)malloc(TEST_ANCESTORS*sizeof(RuleProcessorData*));
+ 
+ #endif
+ #endif
  
  struct RuleValue {
    /**
***************
*** 1771,1777 ****
--- 1791,2130 ----
  //   '+' and '>', the direct adjacent sibling and child combinators, are not
  #define NS_IS_GREEDY_OPERATOR(ch) (ch == PRUnichar(0) || ch == PRUnichar('~'))
  
+ #ifdef CUSTOM_SMT
+ static PRBool SelectorMatchesTree(RuleProcessorData& aPrevData,
+                                   nsCSSSelector* aSelector,
+                                   PRBool aForStyling) 
+ {
+   nsCSSSelector* selector = aSelector;
+   RuleProcessorData* prevdata = &aPrevData;
  
+   int n = 0, p;
+   nsCSSSelector* tempSelector = selector;
+   RuleProcessorData* tempData = prevdata, *secondData;
+   PRBool* tempResults;		
+   SharedData* result;
+ 
+   //preprocess data necessary to determine if conditions needed to apply SM parallelization are fulfilled
+   while (tempSelector)
+ 	{
+ 		n++;
+ 		tempSelector = tempSelector->mNext;	
+ 	}
+ 
+   if ((n == 1) && (selector->mOperator == PRUnichar(0)) && (!selector->mPseudoClassList) && (!selector->mAttrList) && (!selector->mNegations)) // right now we are only ||zing the calls where there's only "one" selector
+   {
+ 	m = 0;
+ 	while (tempData)
+ 	{
+ 		secondData = tempData->mParentData;
+ 		if (!secondData)
+ 		{
+ 			nsIContent *content = tempData->mContent->GetParent();
+ 			// GetParent could return a document fragment; we only want
+ 			// element parents.
+ 			if (content && content->IsNodeOfType(nsINode::eELEMENT)) {
+ 				secondData = RuleProcessorData::Create(tempData->mPresContext, content,
+ 														   tempData->mRuleWalker,
+ 														   tempData->mCompatMode);
+ 			}
+ 			tempData->mParentData = secondData;    
+ 		}
+ 		if (!secondData) break;
+ 
+ 		if (m < TEST_ANCESTORS) tempAncestors[m] = secondData; // we'll asusme that 128 is large enough for now
+ 		m++;
+ 		tempData = secondData;
+ 	}
+ 
+ 	// check if conditions necessary in order to apply SM parallelization are fulfilled
+ 	if (m > 27)
+ 	{
+ #ifdef C_DEBUG
+ 	
+ 		/* For testing purposes ONLY*/ 
+ 		bool matchFound = false;
+ 		int tempIndexFound = -1;
+ 		tempResults = (PRBool *)malloc(m*sizeof(PRBool));
+ 	
+ 		for (p = 0; p < m; p++)
+ 		{
+ 			tempResults[p] = SelectorMatches(*(tempAncestors[p]), selector, 0, nsnull, aForStyling);
+ 			if (tempResults[p]) {matchFound = true; if (tempIndexFound == -1) tempIndexFound = p;}
+ 		}
+ 		/* End testing portion */
+ #endif	
+ 		if (!threads_created) 
+ 		{
+ #ifdef C_DEBUG
+ 			if (f == NULL)
+ 			{
+ 				  f = fopen("traceOutput.txt", "a");
+ 			}
+ 			
+ 			/* For testing porposes ONLY */			
+ 			fprintf(f, "Matching results: ");
+ 			for (p = 0; p < m; p++)
+ 			{
+ 				fprintf(f, "%d", tempResults[p]);
+ 			}
+ 			fprintf(f, "\n\n");
+ 			/* End testing portion */
+ #endif
+ 			for (p = 0; p < NUM_THREADS; p++)
+ 			{
+ 			  tData[p] = new ThreadData(selector, NULL, aForStyling, threadid++, -1, -1, -1); 
+ 			}
+ 			mainThread = new SelectorMainThread(tData, f, selector, prevdata);
+ 
+ #ifdef C_DEBUG
+ 			fprintf(f, "in MAIN(), before calling mainThread->start()\n");
+ #endif	  
+ 			result = mainThread->startOrWakeup(0, m, tempAncestors, NULL, NULL);
+ 
+ #ifdef C_DEBUG
+ 			fprintf(f, "in MAIN(), after calling mainThread->start(); foundIndex = %d, availableAncestorIndex = %d, WaitForThreads = %d\n", result->foundIndex, result->availableAncestorIndex, result->WaitForThreads);
+ #endif
+ /*
+ #ifdef C_DEBUG
+ 			fprintf(f, "in main, before calling mainThread.terminate()\n");
+ #endif
+ 			mainThread->terminate();
+ 
+ #ifdef C_DEBUG
+ 			fprintf(f, "in main, after calling mainThread.terminate()\n");
+ 			//for Visual Studio debugging - fclose(f);
+ #endif
+ */
+ 			/*
+ 			delete mainThread;
+ 			for (p = 0; p < NUM_THREADS; p++)
+ 			{
+ 			  delete tData[p];
+ 			}
+ 			*/
+ 			threads_created = true;
+ 		}
+ 		
+ 		else //if (threads_created2 < 15000)
+ 		{
+ #ifdef C_DEBUG
+ 			if (f == NULL)
+ 			{
+ 				  f = fopen("traceOutput.txt", "a");
+ 			}
+ 			
+ 			/* For testing purposes ONLY */			
+ 			fprintf(f, "Matching results: ");
+ 			for (p = 0; p < m; p++)
+ 			{
+ 				fprintf(f, "%d", tempResults[p]);
+ 			}
+ 			fprintf(f, "\n\n");
+ 			/* End testing portion */
+ #endif
+ 
+ #ifdef C_DEBUG
+ 			fprintf(f, "in MAIN(), before calling mainThread->wakeup()\n");
+ #endif	
+ 			result = mainThread->startOrWakeup(1, m, tempAncestors, f, selector);
+ #ifdef C_DEBUG
+ 			fprintf(f, "in MAIN(), after calling mainThread->wakeup(); foundIndex = %d, availableAncestorIndex = %d\n", result->foundIndex, result->availableAncestorIndex);
+ #endif
+ 			//threads_created2++;
+ 		}
+ 		return result->found;
+ 	}
+ 	else
+ 	{
+ 	  while (selector) { // check compound selectors
+ 
+ 		// If we don't already have a RuleProcessorData for the next
+ 		// appropriate content (whether parent or previous sibling), create
+ 		// one.
+ 
+ 		// for adjacent sibling combinators, the content to test against the
+ 		// selector is the previous sibling *element*
+ 		RuleProcessorData* data;
+ 
+ 		if (PRUnichar('+') == selector->mOperator ||
+ 			PRUnichar('~') == selector->mOperator) {
+ 
+ 		  data = prevdata->mPreviousSiblingData;
+ 
+ 		  if (!data) {        
+ 			nsIContent* content = prevdata->mContent;
+ 			nsIContent* parent = content->GetParent();
+ 			if (parent) {
+ 			  parent->SetFlags(NODE_HAS_SLOW_SELECTOR_NOAPPEND);
+ 
+ 			  PRInt32 index = parent->IndexOf(content);
+ 			  while (0 <= --index) {
+ 				content = parent->GetChildAt(index);
+ 				if (content->IsNodeOfType(nsINode::eELEMENT)) {
+ 				  data = RuleProcessorData::Create(prevdata->mPresContext, content,
+ 												   prevdata->mRuleWalker,
+ 												   prevdata->mCompatMode);
+ 				  prevdata->mPreviousSiblingData = data;    
+ 				  break;
+ 				}
+ 			  }
+ 			}
+ 		  }
+ 		}
+ 		// for descendant combinators and child combinators, the content
+ 		// to test against is the parent
+ 		else {
+ 		  data = prevdata->mParentData;
+ 		  if (!data) {
+ 			nsIContent *content = prevdata->mContent->GetParent();
+ 			// GetParent could return a document fragment; we only want
+ 			// element parents.
+ 			if (content && content->IsNodeOfType(nsINode::eELEMENT)) {
+ 			  data = RuleProcessorData::Create(prevdata->mPresContext, content,
+ 											   prevdata->mRuleWalker,
+ 											   prevdata->mCompatMode);
+ 			  prevdata->mParentData = data;    
+ 			}
+ 		  }
+ 		}    
+ 		if (! data) {
+ 		  return PR_FALSE;
+ 		}
+ 
+ 		if (SelectorMatches(*data, selector, 0, nsnull, aForStyling)) { 
+ 		  // to avoid greedy matching, we need to recur if this is a
+ 		  // descendant or general sibling combinator and the next
+ 		  // combinator is different, but we can make an exception for
+ 		  // sibling, then parent, since a sibling's parent is always the
+ 		  // same.
+ 		  if ((NS_IS_GREEDY_OPERATOR(selector->mOperator)) &&
+ 			  (selector->mNext) &&
+ 			  (selector->mNext->mOperator != selector->mOperator) &&
+ 			  !(selector->mOperator == '~' &&
+ 				selector->mNext->mOperator == PRUnichar(0))) {
+ 	        
+ 			// pretend the selector didn't match, and step through content
+ 			// while testing the same selector
+ 
+ 			// This approach is slightly strange in that when it recurs
+ 			// it tests from the top of the content tree, down.  This
+ 			// doesn't matter much for performance since most selectors
+ 			// don't match.  (If most did, it might be faster...)
+ 			if (SelectorMatchesTree(*data, selector, aForStyling)) {    
+ 			  return PR_TRUE;
+ 			}
+ 		  }
+ 		  selector = selector->mNext;
+ 		}
+ 		else {
+ 		  // for adjacent sibling and child combinators, if we didn't find
+ 		  // a match, we're done
+ 		  if (!NS_IS_GREEDY_OPERATOR(selector->mOperator)) {      
+ 			return PR_FALSE;  // parent was required to match
+ 		  }
+ 		}
+ 		prevdata = data;
+ 	  }
+ 	  return PR_TRUE; // all the selectors matched.
+ 	  }
+ 	  }
+ 	  else 
+ 	  {
+ 		  while (selector) { // check compound selectors
+ 
+ 			// If we don't already have a RuleProcessorData for the next
+ 			// appropriate content (whether parent or previous sibling), create
+ 			// one.
+ 
+ 			// for adjacent sibling combinators, the content to test against the
+ 			// selector is the previous sibling *element*
+ 			RuleProcessorData* data;
+ 
+ 			if (PRUnichar('+') == selector->mOperator ||
+ 				PRUnichar('~') == selector->mOperator) {
+ 
+ 			  data = prevdata->mPreviousSiblingData;
+ 
+ 			  if (!data) {        
+ 				nsIContent* content = prevdata->mContent;
+ 				nsIContent* parent = content->GetParent();
+ 				if (parent) {
+ 				  parent->SetFlags(NODE_HAS_SLOW_SELECTOR_NOAPPEND);
+ 
+ 				  PRInt32 index = parent->IndexOf(content);
+ 				  while (0 <= --index) {
+ 					content = parent->GetChildAt(index);
+ 					if (content->IsNodeOfType(nsINode::eELEMENT)) {
+ 					  data = RuleProcessorData::Create(prevdata->mPresContext, content,
+ 													   prevdata->mRuleWalker,
+ 													   prevdata->mCompatMode);
+ 					  prevdata->mPreviousSiblingData = data;    
+ 					  break;
+ 					}
+ 				  }
+ 				}
+ 			  }
+ 			}
+ 			// for descendant combinators and child combinators, the content
+ 			// to test against is the parent
+ 			else {
+ 			  data = prevdata->mParentData;
+ 			  if (!data) {
+ 				nsIContent *content = prevdata->mContent->GetParent();
+ 				// GetParent could return a document fragment; we only want
+ 				// element parents.
+ 				if (content && content->IsNodeOfType(nsINode::eELEMENT)) {
+ 				  data = RuleProcessorData::Create(prevdata->mPresContext, content,
+ 												   prevdata->mRuleWalker,
+ 												   prevdata->mCompatMode);
+ 				  prevdata->mParentData = data;    
+ 				}
+ 			  }
+ 			}    
+ 			if (! data) {
+ 			  return PR_FALSE;
+ 			}
+ 
+ 			if (SelectorMatches(*data, selector, 0, nsnull, aForStyling)) { 
+ 			  // to avoid greedy matching, we need to recur if this is a
+ 			  // descendant or general sibling combinator and the next
+ 			  // combinator is different, but we can make an exception for
+ 			  // sibling, then parent, since a sibling's parent is always the
+ 			  // same.
+ 			  if ((NS_IS_GREEDY_OPERATOR(selector->mOperator)) &&
+ 				  (selector->mNext) &&
+ 				  (selector->mNext->mOperator != selector->mOperator) &&
+ 				  !(selector->mOperator == '~' &&
+ 					selector->mNext->mOperator == PRUnichar(0))) {
+ 		        
+ 				// pretend the selector didn't match, and step through content
+ 				// while testing the same selector
+ 
+ 				// This approach is slightly strange in that when it recurs
+ 				// it tests from the top of the content tree, down.  This
+ 				// doesn't matter much for performance since most selectors
+ 				// don't match.  (If most did, it might be faster...)
+ 				if (SelectorMatchesTree(*data, selector, aForStyling)) {    
+ 				  return PR_TRUE;
+ 				}
+ 			  }
+ 			  selector = selector->mNext;
+ 			}
+ 			else {
+ 			  // for adjacent sibling and child combinators, if we didn't find
+ 			  // a match, we're done
+ 			  if (!NS_IS_GREEDY_OPERATOR(selector->mOperator)) {      
+ 				return PR_FALSE;  // parent was required to match
+ 			  }
+ 			}
+ 			prevdata = data;
+ 		  }
+ 		  return PR_TRUE; // all the selectors matched.
+ }
+ }
+ 
+ #else
  static PRBool SelectorMatchesTree(RuleProcessorData& aPrevData,
                                    nsCSSSelector* aSelector,
                                    PRBool aForStyling) 
***************
*** 1864,1869 ****
--- 2217,2223 ----
    }
    return PR_TRUE; // all the selectors matched.
  }
+ #endif
  
  static void ContentEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
                              void* aData)
