/[jscoverage]/trunk/js/jslock.cpp
ViewVC logotype

Diff of /trunk/js/jslock.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 460 by siliconforks, Sat Sep 26 23:15:22 2009 UTC revision 507 by siliconforks, Sun Jan 10 07:23:34 2010 UTC
# Line 1  Line 1 
1  /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-  /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2   *   *
3   * ***** BEGIN LICENSE BLOCK *****   * ***** BEGIN LICENSE BLOCK *****
4   * Version: MPL 1.1/GPL 2.0/LGPL 2.1   * Version: MPL 1.1/GPL 2.0/LGPL 2.1
# Line 42  Line 42 
42  /*  /*
43   * JS locking stubs.   * JS locking stubs.
44   */   */
 #include "jsstddef.h"  
45  #include <stdlib.h>  #include <stdlib.h>
46  #include <string.h>  #include <string.h>
47  #include "jspubtd.h"  #include "jspubtd.h"
48  #include "jsutil.h" /* Added by JSIFY */  #include "jsutil.h" /* Added by JSIFY */
49  #include "jstypes.h"  #include "jstypes.h"
50    #include "jsstdint.h"
51  #include "jsbit.h"  #include "jsbit.h"
52  #include "jscntxt.h"  #include "jscntxt.h"
53  #include "jsdtoa.h"  #include "jsdtoa.h"
54  #include "jsgc.h"  #include "jsgc.h"
55  #include "jsfun.h"      /* for VALUE_IS_FUNCTION used by *_WRITE_BARRIER */  #include "jsfun.h"      /* for VALUE_IS_FUNCTION from LOCKED_OBJ_WRITE_SLOT */
56  #include "jslock.h"  #include "jslock.h"
57  #include "jsscope.h"  #include "jsscope.h"
58  #include "jsstr.h"  #include "jsstr.h"
59    
60  #define ReadWord(W) (W)  #define ReadWord(W) (W)
61    
62    #if !defined(__GNUC__)
63    # define __asm__ asm
64    # define __volatile__ volatile
65    #endif
66    
67  /* Implement NativeCompareAndSwap. */  /* Implement NativeCompareAndSwap. */
68    
69  #if defined(_WIN32) && defined(_M_IX86)  #if defined(_WIN32) && defined(_M_IX86)
# Line 86  Line 91 
91      return (NativeCompareAndSwapHelper(w, ov, nv) & 1);      return (NativeCompareAndSwapHelper(w, ov, nv) & 1);
92  }  }
93    
94    #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_X64))
95    JS_BEGIN_EXTERN_C
96    extern long long __cdecl
97    _InterlockedCompareExchange64(long long *volatile dest, long long exchange, long long comp);
98    JS_END_EXTERN_C
99    #pragma intrinsic(_InterlockedCompareExchange64)
100    
101    static JS_ALWAYS_INLINE int
102    NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
103    {
104        return _InterlockedCompareExchange64(w, nv, ov) == ov;
105    }
106    
107  #elif defined(XP_MACOSX) || defined(DARWIN)  #elif defined(XP_MACOSX) || defined(DARWIN)
108    
109  #include <libkern/OSAtomic.h>  #include <libkern/OSAtomic.h>
# Line 97  Line 115 
115      return OSAtomicCompareAndSwapPtrBarrier(ov, nv, w);      return OSAtomicCompareAndSwapPtrBarrier(ov, nv, w);
116  }  }
117    
118  #elif defined(__GNUC__) && defined(__i386__)  #elif defined(__i386) && (defined(__GNUC__) || defined(__SUNPRO_CC))
119    
120  /* Note: This fails on 386 cpus, cmpxchgl is a >= 486 instruction */  /* Note: This fails on 386 cpus, cmpxchgl is a >= 486 instruction */
121  static JS_ALWAYS_INLINE int  static JS_ALWAYS_INLINE int
# Line 116  Line 134 
134      return (int)res;      return (int)res;
135  }  }
136    
137  #elif defined(__GNUC__) && defined(__x86_64__)  #elif defined(__x86_64) && (defined(__GNUC__) || defined(__SUNPRO_CC))
138    
139  static JS_ALWAYS_INLINE int  static JS_ALWAYS_INLINE int
140  NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)  NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
141  {  {
# Line 133  Line 152 
152      return (int)res;      return (int)res;
153  }  }
154    
155  #elif defined(SOLARIS) && defined(sparc) && defined(ULTRA_SPARC)  #elif defined(__sparc) && (defined(__GNUC__) || defined(__SUNPRO_CC))
156    
157  static JS_ALWAYS_INLINE int  static JS_ALWAYS_INLINE int
158  NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)  NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
159  {  {
 #if defined(__GNUC__)  
160      unsigned int res;      unsigned int res;
161      JS_ASSERT(ov != nv);  
162      asm volatile ("\      __asm__ __volatile__ (
163  stbar\n\                    "stbar\n"
164  cas [%1],%2,%3\n\                    "cas [%1],%2,%3\n"
165  cmp %2,%3\n\                    "cmp %2,%3\n"
166  be,a 1f\n\                    "be,a 1f\n"
167  mov 1,%0\n\                    "mov 1,%0\n"
168  mov 0,%0\n\                    "mov 0,%0\n"
169  1:"                    "1:"
170                    : "=r" (res)                    : "=r" (res)
171                    : "r" (w), "r" (ov), "r" (nv));                    : "r" (w), "r" (ov), "r" (nv));
172      return (int)res;      return (int)res;
 #else /* !__GNUC__ */  
     extern int compare_and_swap(jsword*, jsword, jsword);  
     JS_ASSERT(ov != nv);  
     return compare_and_swap(w, ov, nv);  
 #endif  
173  }  }
174    
175  #elif defined(AIX)  #elif defined(AIX)
# Line 210  Line 223 
223  #elif defined(NSPR_LOCK)  #elif defined(NSPR_LOCK)
224    
225  # ifdef __GNUC__  # ifdef __GNUC__
226  # warning "js_CompareAndSwap is implemented using NSSP lock"  # warning "js_CompareAndSwap is implemented using NSPR lock"
227  # endif  # endif
228    
229  JSBool  JSBool
# Line 443  Line 456 
456   * to do this because such strings will soon be available to multiple threads,   * to do this because such strings will soon be available to multiple threads,
457   * so their buffers can't be realloc'd any longer in js_ConcatStrings, and   * so their buffers can't be realloc'd any longer in js_ConcatStrings, and
458   * their members can't be modified by js_ConcatStrings, js_UndependString or   * their members can't be modified by js_ConcatStrings, js_UndependString or
459   * js_MinimizeDependentStrings.   * MinimizeDependentStrings.
460   *   *
461   * The last bit of work done by this function nulls title->ownercx and updates   * The last bit of work done by this function nulls title->ownercx and updates
462   * rt->sharedTitles.   * rt->sharedTitles.
# Line 451  Line 464 
464  static void  static void
465  FinishSharingTitle(JSContext *cx, JSTitle *title)  FinishSharingTitle(JSContext *cx, JSTitle *title)
466  {  {
     JSScope *scope;  
     JSObject *obj;  
     uint32 nslots, i;  
     jsval v;  
   
467      js_InitLock(&title->lock);      js_InitLock(&title->lock);
468      title->u.count = 0;     /* NULL may not pun as 0 */      title->u.count = 0;     /* NULL may not pun as 0 */
469      scope = TITLE_TO_SCOPE(title);  
470      obj = scope->object;      JSScope *scope = TITLE_TO_SCOPE(title);
471        JSObject *obj = scope->object;
472      if (obj) {      if (obj) {
473          nslots = scope->freeslot;          uint32 nslots = scope->freeslot;
474          for (i = 0; i != nslots; ++i) {          JS_ASSERT(nslots >= JSSLOT_START(obj->getClass()));
475              v = STOBJ_GET_SLOT(obj, i);          for (uint32 i = JSSLOT_START(obj->getClass()); i != nslots; ++i) {
476                jsval v = STOBJ_GET_SLOT(obj, i);
477              if (JSVAL_IS_STRING(v) &&              if (JSVAL_IS_STRING(v) &&
478                  !js_MakeStringImmutable(cx, JSVAL_TO_STRING(v))) {                  !js_MakeStringImmutable(cx, JSVAL_TO_STRING(v))) {
479                  /*                  /*
# Line 607  Line 617 
617           * non-null test, and avoid double-insertion bugs.           * non-null test, and avoid double-insertion bugs.
618           */           */
619          if (!title->u.link) {          if (!title->u.link) {
620              js_HoldScope(TITLE_TO_SCOPE(title));              TITLE_TO_SCOPE(title)->hold();
621              title->u.link = rt->titleSharingTodo;              title->u.link = rt->titleSharingTodo;
622              rt->titleSharingTodo = title;              rt->titleSharingTodo = title;
623          }          }
# Line 683  Line 693 
693          title->u.link = NULL;       /* null u.link for sanity ASAP */          title->u.link = NULL;       /* null u.link for sanity ASAP */
694    
695          /*          /*
696           * If js_DropScope returns false, we held the last ref to scope. The           * If JSScope::drop returns false, we held the last ref to scope. The
697           * waiting thread(s) must have been killed, after which the GC           * waiting thread(s) must have been killed, after which the GC
698           * collected the object that held this scope.  Unlikely, because it           * collected the object that held this scope.  Unlikely, because it
699           * requires that the GC ran (e.g., from an operation callback)           * requires that the GC ran (e.g., from an operation callback)
700           * during this request, but possible.           * during this request, but possible.
701           */           */
702          if (js_DropScope(cx, TITLE_TO_SCOPE(title), NULL)) {          if (TITLE_TO_SCOPE(title)->drop(cx, NULL)) {
703              FinishSharingTitle(cx, title); /* set ownercx = NULL */              FinishSharingTitle(cx, title); /* set ownercx = NULL */
704              shared = true;              shared = true;
705          }          }
# Line 710  Line 720 
720      jsword me;      jsword me;
721  #endif  #endif
722    
723      /*      OBJ_CHECK_SLOT(obj, slot);
      * We handle non-native objects via JSObjectOps.getRequiredSlot, treating  
      * all slots starting from 0 as required slots.  A property definition or  
      * some prior arrangement must have allocated slot.  
      *  
      * Note once again (see jspubtd.h, before JSGetRequiredSlotOp's typedef)  
      * the crucial distinction between a |required slot number| that's passed  
      * to the get/setRequiredSlot JSObjectOps, and a |reserved slot index|  
      * passed to the JS_Get/SetReservedSlot APIs.  
      */  
     if (!OBJ_IS_NATIVE(obj))  
         return OBJ_GET_REQUIRED_SLOT(cx, obj, slot);  
724    
725      /*      /*
726       * Native object locking is inlined here to optimize the single-threaded       * Native object locking is inlined here to optimize the single-threaded
# Line 739  Line 738 
738       * an earlier request.       * an earlier request.
739       */       */
740      if (CX_THREAD_IS_RUNNING_GC(cx) ||      if (CX_THREAD_IS_RUNNING_GC(cx) ||
741          (SCOPE_IS_SEALED(scope) && scope->object == obj) ||          scope->sealed() ||
742          (title->ownercx && ClaimTitle(title, cx))) {          (title->ownercx && ClaimTitle(title, cx))) {
743          return STOBJ_GET_SLOT(obj, slot);          return STOBJ_GET_SLOT(obj, slot);
744      }      }
# Line 802  Line 801 
801      jsword me;      jsword me;
802  #endif  #endif
803    
804        OBJ_CHECK_SLOT(obj, slot);
805    
806      /* Any string stored in a thread-safe object must be immutable. */      /* Any string stored in a thread-safe object must be immutable. */
807      if (JSVAL_IS_STRING(v) &&      if (JSVAL_IS_STRING(v) &&
808          !js_MakeStringImmutable(cx, JSVAL_TO_STRING(v))) {          !js_MakeStringImmutable(cx, JSVAL_TO_STRING(v))) {
# Line 810  Line 811 
811      }      }
812    
813      /*      /*
      * We handle non-native objects via JSObjectOps.setRequiredSlot, as above  
      * for the Get case.  
      */  
     if (!OBJ_IS_NATIVE(obj)) {  
         OBJ_SET_REQUIRED_SLOT(cx, obj, slot, v);  
         return;  
     }  
   
     /*  
814       * Native object locking is inlined here to optimize the single-threaded       * Native object locking is inlined here to optimize the single-threaded
815       * and contention-free multi-threaded cases.       * and contention-free multi-threaded cases.
816       */       */
# Line 834  Line 826 
826       * an earlier request.       * an earlier request.
827       */       */
828      if (CX_THREAD_IS_RUNNING_GC(cx) ||      if (CX_THREAD_IS_RUNNING_GC(cx) ||
829          (SCOPE_IS_SEALED(scope) && scope->object == obj) ||          scope->sealed() ||
830          (title->ownercx && ClaimTitle(title, cx))) {          (title->ownercx && ClaimTitle(title, cx))) {
831          LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, v);          LOCKED_OBJ_WRITE_SLOT(cx, obj, slot, v);
832          return;          return;
833      }      }
834    
# Line 846  Line 838 
838      JS_ASSERT(CURRENT_THREAD_IS_ME(me));      JS_ASSERT(CURRENT_THREAD_IS_ME(me));
839      if (NativeCompareAndSwap(&tl->owner, 0, me)) {      if (NativeCompareAndSwap(&tl->owner, 0, me)) {
840          if (scope == OBJ_SCOPE(obj)) {          if (scope == OBJ_SCOPE(obj)) {
841              LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, v);              LOCKED_OBJ_WRITE_SLOT(cx, obj, slot, v);
842              if (!NativeCompareAndSwap(&tl->owner, me, 0)) {              if (!NativeCompareAndSwap(&tl->owner, me, 0)) {
843                  /* Assert that scope locks never revert to flyweight. */                  /* Assert that scope locks never revert to flyweight. */
844                  JS_ASSERT(title->ownercx != cx);                  JS_ASSERT(title->ownercx != cx);
# Line 860  Line 852 
852              js_Dequeue(tl);              js_Dequeue(tl);
853      }      }
854      else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) {      else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) {
855          LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, v);          LOCKED_OBJ_WRITE_SLOT(cx, obj, slot, v);
856          return;          return;
857      }      }
858  #endif  #endif
859    
860      js_LockObj(cx, obj);      js_LockObj(cx, obj);
861      LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, v);      LOCKED_OBJ_WRITE_SLOT(cx, obj, slot, v);
862    
863      /*      /*
864       * Same drill as above, in js_GetSlotThreadSafe.       * Same drill as above, in js_GetSlotThreadSafe.
# Line 896  Line 888 
888  {  {
889      PR_DestroyLock(fl->slock);      PR_DestroyLock(fl->slock);
890      PR_DestroyCondVar(fl->svar);      PR_DestroyCondVar(fl->svar);
891      free(fl);      js_free(fl);
892  }  }
893    
894  static JSFatLock *  static JSFatLock *
# Line 990  Line 982 
982      global_locks_log2 = JS_CeilingLog2(globc);      global_locks_log2 = JS_CeilingLog2(globc);
983      global_locks_mask = JS_BITMASK(global_locks_log2);      global_locks_mask = JS_BITMASK(global_locks_log2);
984      global_lock_count = JS_BIT(global_locks_log2);      global_lock_count = JS_BIT(global_locks_log2);
985      global_locks = (PRLock **) malloc(global_lock_count * sizeof(PRLock*));      global_locks = (PRLock **) js_malloc(global_lock_count * sizeof(PRLock*));
986      if (!global_locks)      if (!global_locks)
987          return JS_FALSE;          return JS_FALSE;
988      for (i = 0; i < global_lock_count; i++) {      for (i = 0; i < global_lock_count; i++) {
# Line 1001  Line 993 
993              return JS_FALSE;              return JS_FALSE;
994          }          }
995      }      }
996      fl_list_table = (JSFatLockTable *) malloc(i * sizeof(JSFatLockTable));      fl_list_table = (JSFatLockTable *) js_malloc(i * sizeof(JSFatLockTable));
997      if (!fl_list_table) {      if (!fl_list_table) {
998          js_CleanupLocks();          js_CleanupLocks();
999          return JS_FALSE;          return JS_FALSE;
# Line 1023  Line 1015 
1015      if (global_locks) {      if (global_locks) {
1016          for (i = 0; i < global_lock_count; i++)          for (i = 0; i < global_lock_count; i++)
1017              PR_DestroyLock(global_locks[i]);              PR_DestroyLock(global_locks[i]);
1018          free(global_locks);          js_free(global_locks);
1019          global_locks = NULL;          global_locks = NULL;
1020          global_lock_count = 1;          global_lock_count = 1;
1021          global_locks_log2 = 0;          global_locks_log2 = 0;
# Line 1036  Line 1028 
1028              DeleteListOfFatlocks(fl_list_table[i].taken);              DeleteListOfFatlocks(fl_list_table[i].taken);
1029              fl_list_table[i].taken = NULL;              fl_list_table[i].taken = NULL;
1030          }          }
1031          free(fl_list_table);          js_free(fl_list_table);
1032          fl_list_table = NULL;          fl_list_table = NULL;
1033          fl_list_table_len = 0;          fl_list_table_len = 0;
1034      }      }
# Line 1398  Line 1390 
1390      for (;;) {      for (;;) {
1391          scope = OBJ_SCOPE(obj);          scope = OBJ_SCOPE(obj);
1392          title = &scope->title;          title = &scope->title;
1393          if (SCOPE_IS_SEALED(scope) && scope->object == obj &&          if (scope->sealed() && !cx->lockedSealedTitle) {
             !cx->lockedSealedTitle) {  
1394              cx->lockedSealedTitle = title;              cx->lockedSealedTitle = title;
1395              return;              return;
1396          }          }
# Line 1422  Line 1413 
1413      js_UnlockTitle(cx, &OBJ_SCOPE(obj)->title);      js_UnlockTitle(cx, &OBJ_SCOPE(obj)->title);
1414  }  }
1415    
1416    bool
1417    js_LockObjIfShape(JSContext *cx, JSObject *obj, uint32 shape)
1418    {
1419        JS_ASSERT(OBJ_SCOPE(obj)->title.ownercx != cx);
1420        js_LockObj(cx, obj);
1421        if (OBJ_SHAPE(obj) == shape)
1422            return true;
1423        js_UnlockObj(cx, obj);
1424        return false;
1425    }
1426    
1427  void  void
1428  js_InitTitle(JSContext *cx, JSTitle *title)  js_InitTitle(JSContext *cx, JSTitle *title)
1429  {  {
# Line 1501  Line 1503 
1503      JSTitle *title = &scope->title;      JSTitle *title = &scope->title;
1504      if (!title->ownercx) {      if (!title->ownercx) {
1505          jsrefcount count = title->u.count;          jsrefcount count = title->u.count;
1506          JS_ASSERT_IF(!SCOPE_IS_SEALED(scope), count > 0);          JS_ASSERT_IF(!scope->sealed(), count > 0);
1507          JS_ASSERT(count <= 4);          JS_ASSERT(count <= 4);
1508          title->file[count - 1] = file;          title->file[count - 1] = file;
1509          title->line[count - 1] = line;          title->line[count - 1] = line;

Legend:
Removed from v.460  
changed lines
  Added in v.507

  ViewVC Help
Powered by ViewVC 1.1.24