Bug 717762: Proliferate js_memcpy and PodCopy. (r=luke)
☠☠ backed out by 4dd329d75054 ☠ ☠
authorChris Leary <cdleary@mozilla.com>
Thu, 12 Jan 2012 18:40:08 -0800
changeset 84416 b36175bbda47da731573c8031a132a4f2385235d
parent 84415 254f355a4a9605a1879326ffdc2ac8e0215c35b8
child 84417 f4d1511c16ba1821a72aa124988e1231758e9635
push id4894
push usercleary@mozilla.com
push dateSat, 14 Jan 2012 01:12:54 +0000
treeherdermozilla-inbound@b36175bbda47 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs717762
milestone12.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 717762: Proliferate js_memcpy and PodCopy. (r=luke)
js/src/ds/LifoAlloc.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/Parser.h
js/src/frontend/TokenStream.cpp
js/src/jsapi-tests/testConservativeGC.cpp
js/src/jsapi-tests/testXDR.cpp
js/src/jsapi.cpp
js/src/jsclone.cpp
js/src/jscrashreport.cpp
js/src/jsdbgapi.cpp
js/src/jsdhash.cpp
js/src/jsdtoa.cpp
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsinfer.cpp
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobjinlines.h
js/src/jsopcode.cpp
js/src/jsprf.cpp
js/src/jsscript.cpp
js/src/jsstr.cpp
js/src/jsstr.h
js/src/jstypedarray.cpp
js/src/jsutil.cpp
js/src/jsutil.h
js/src/jsxdrapi.cpp
js/src/shell/js.cpp
--- a/js/src/ds/LifoAlloc.cpp
+++ b/js/src/ds/LifoAlloc.cpp
@@ -218,10 +218,10 @@ LifoAlloc::reallocUnaligned(void *origPt
         && latest->canAllocUnaligned(incr)) {
         JS_ALWAYS_TRUE(allocUnaligned(incr));
         return origPtr;
     }
 
     /* Otherwise, memcpy. */
     size_t newSize = origSize + incr;
     void *newPtr = allocUnaligned(newSize);
-    return newPtr ? memcpy(newPtr, origPtr, origSize) : NULL;
+    return newPtr ? js_memcpy(newPtr, origPtr, origSize) : NULL;
 }
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -7048,18 +7048,18 @@ frontend::FinishTakingSrcNotes(JSContext
                 sn = bce->main.notes;
             }
         }
     }
 
     mainCount = bce->main.noteCount;
     totalCount = prologCount + mainCount;
     if (prologCount)
-        memcpy(notes, bce->prolog.notes, SRCNOTE_SIZE(prologCount));
-    memcpy(notes + prologCount, bce->main.notes, SRCNOTE_SIZE(mainCount));
+        PodCopy(notes, bce->prolog.notes, prologCount);
+    PodCopy(notes + prologCount, bce->main.notes, mainCount);
     SN_MAKE_TERMINATOR(&notes[totalCount]);
 
     return true;
 }
 
 static JSBool
 NewTryNote(JSContext *cx, BytecodeEmitter *bce, JSTryNoteKind kind, uintN stackDepth, size_t start,
            size_t end)
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -159,17 +159,17 @@ struct Parser : private AutoGCRooter
 
     /* new_ methods for creating parse nodes. These report OOM on context. */
     JS_DECLARE_NEW_METHODS(allocParseNode, inline)
 
     ParseNode *cloneNode(const ParseNode &other) {
         ParseNode *node = allocParseNode(sizeof(ParseNode));
         if (!node)
             return NULL;
-        memcpy(node, &other, sizeof(*node));
+        PodAssign(node, &other);
         return node;
     }
 
     /* Public entry points for parsing. */
     ParseNode *statement();
     bool recognizeDirectivePrologue(ParseNode *pn, bool *isDirectivePrologueMember);
 
     /*
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -480,17 +480,17 @@ TokenStream::reportCompileErrorNumberVA(
     if (report.lineno == lineno) {
         size_t linelength = userbuf.findEOL() - linebase;
 
         linechars = (jschar *)cx->malloc_((linelength + 1) * sizeof(jschar));
         if (!linechars) {
             warning = false;
             goto out;
         }
-        memcpy(linechars, linebase, linelength * sizeof(jschar));
+        PodCopy(linechars, linebase, linelength);
         linechars[linelength] = 0;
         linebytes = DeflateString(cx, linechars, linelength);
         if (!linebytes) {
             warning = false;
             goto out;
         }
 
         /* Unicode and char versions of the offending source line, without final \n */
--- a/js/src/jsapi-tests/testConservativeGC.cpp
+++ b/js/src/jsapi-tests/testConservativeGC.cpp
@@ -3,29 +3,29 @@
 #include "vm/String.h"
 
 BEGIN_TEST(testConservativeGC)
 {
     jsval v2;
     EVAL("({foo: 'bar'});", &v2);
     CHECK(JSVAL_IS_OBJECT(v2));
     char objCopy[sizeof(JSObject)];
-    memcpy(&objCopy, JSVAL_TO_OBJECT(v2), sizeof(JSObject));
+    js_memcpy(&objCopy, JSVAL_TO_OBJECT(v2), sizeof(JSObject));
 
     jsval v3;
     EVAL("String(Math.PI);", &v3);
     CHECK(JSVAL_IS_STRING(v3));
     JSString strCopy = *JSVAL_TO_STRING(v3);
 
     jsval tmp;
     EVAL("({foo2: 'bar2'});", &tmp);
     CHECK(JSVAL_IS_OBJECT(tmp));
     JSObject *obj2 = JSVAL_TO_OBJECT(tmp);
     char obj2Copy[sizeof(JSObject)];
-    memcpy(&obj2Copy, obj2, sizeof(JSObject));
+    js_memcpy(&obj2Copy, obj2, sizeof(JSObject));
 
     EVAL("String(Math.sqrt(3));", &tmp);
     CHECK(JSVAL_IS_STRING(tmp));
     JSString *str2 = JSVAL_TO_STRING(tmp);
     JSString str2Copy = *str2;
 
     tmp = JSVAL_NULL;
 
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -23,17 +23,17 @@ BEGIN_TEST(testXDR_bug506491)
     JSXDRState *w = JS_XDRNewMem(cx, JSXDR_ENCODE);
     CHECK(w);
     CHECK(JS_XDRScript(w, &script));
     uint32_t nbytes;
     void *p = JS_XDRMemGetData(w, &nbytes);
     CHECK(p);
     void *frozen = JS_malloc(cx, nbytes);
     CHECK(frozen);
-    memcpy(frozen, p, nbytes);
+    js_memcpy(frozen, p, nbytes);
     JS_XDRDestroy(w);
 
     // thaw
     script = NULL;
     JSXDRState *r = JS_XDRNewMem(cx, JSXDR_DECODE);
     JS_XDRMemSetData(r, frozen, nbytes);
     CHECK(JS_XDRScript(r, &script));
     JS_XDRDestroy(r);  // this frees `frozen`
@@ -63,17 +63,17 @@ BEGIN_TEST(testXDR_bug516827)
     JSXDRState *w = JS_XDRNewMem(cx, JSXDR_ENCODE);
     CHECK(w);
     CHECK(JS_XDRScript(w, &script));
     uint32_t nbytes;
     void *p = JS_XDRMemGetData(w, &nbytes);
     CHECK(p);
     void *frozen = JS_malloc(cx, nbytes);
     CHECK(frozen);
-    memcpy(frozen, p, nbytes);
+    js_memcpy(frozen, p, nbytes);
     JS_XDRDestroy(w);
 
     // thaw
     script = NULL;
     JSXDRState *r = JS_XDRNewMem(cx, JSXDR_DECODE);
     JS_XDRMemSetData(r, frozen, nbytes);
     CHECK(JS_XDRScript(r, &script));
     JS_XDRDestroy(r);  // this frees `frozen`
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2228,25 +2228,22 @@ JS_PUBLIC_API(void)
 JS_updateMallocCounter(JSContext *cx, size_t nbytes)
 {
     return cx->runtime->updateMallocCounter(nbytes);
 }
 
 JS_PUBLIC_API(char *)
 JS_strdup(JSContext *cx, const char *s)
 {
-    size_t n;
-    void *p;
-
-    AssertNoGC(cx);
-    n = strlen(s) + 1;
-    p = cx->malloc_(n);
+    AssertNoGC(cx);
+    size_t n = strlen(s) + 1;
+    void *p = cx->malloc_(n);
     if (!p)
         return NULL;
-    return (char *)memcpy(p, s, n);
+    return (char *)js_memcpy(p, s, n);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
 {
     AssertNoGC(cx);
     d = JS_CANONICALIZE_NAN(d);
     rval->setNumber(d);
@@ -2512,17 +2509,17 @@ JS_PrintTraceThingInfo(char *buf, size_t
         name = "xml";
         break;
 #endif
     }
 
     n = strlen(name);
     if (n > bufsize - 1)
         n = bufsize - 1;
-    memcpy(buf, name, n + 1);
+    js_memcpy(buf, name, n + 1);
     buf += n;
     bufsize -= n;
 
     if (details && bufsize > 2) {
         *buf++ = ' ';
         bufsize--;
 
         switch (kind) {
@@ -2626,19 +2623,16 @@ typedef struct JSDumpingTracer {
 } JSDumpingTracer;
 
 static void
 DumpNotify(JSTracer *trc, void *thing, JSGCTraceKind kind)
 {
     JSDumpingTracer *dtrc;
     JSContext *cx;
     JSDHashEntryStub *entry;
-    JSHeapDumpNode *node;
-    const char *edgeName;
-    size_t edgeNameSize;
 
     JS_ASSERT(trc->callback == DumpNotify);
     dtrc = (JSDumpingTracer *)trc;
 
     if (!dtrc->ok || thing == dtrc->thingToIgnore)
         return;
 
     cx = trc->context;
@@ -2667,30 +2661,30 @@ DumpNotify(JSTracer *trc, void *thing, J
             dtrc->ok = JS_FALSE;
             return;
         }
         if (entry->key)
             return;
         entry->key = thing;
     }
 
-    edgeName = JS_GetTraceEdgeName(&dtrc->base, dtrc->buffer, sizeof(dtrc->buffer));
-    edgeNameSize = strlen(edgeName) + 1;
+    const char *edgeName = JS_GetTraceEdgeName(&dtrc->base, dtrc->buffer, sizeof(dtrc->buffer));
+    size_t edgeNameSize = strlen(edgeName) + 1;
     size_t bytes = offsetof(JSHeapDumpNode, edgeName) + edgeNameSize;
-    node = (JSHeapDumpNode *) OffTheBooks::malloc_(bytes);
+    JSHeapDumpNode *node = (JSHeapDumpNode *) OffTheBooks::malloc_(bytes);
     if (!node) {
         dtrc->ok = JS_FALSE;
         return;
     }
 
     node->thing = thing;
     node->kind = kind;
     node->next = NULL;
     node->parent = dtrc->parentNode;
-    memcpy(node->edgeName, edgeName, edgeNameSize);
+    js_memcpy(node->edgeName, edgeName, edgeNameSize);
 
     JS_ASSERT(!*dtrc->lastNodep);
     *dtrc->lastNodep = node;
     dtrc->lastNodep = &node->next;
 }
 
 /* Dump node and the chain that leads to thing it contains. */
 static JSBool
@@ -5496,17 +5490,17 @@ JS_New(JSContext *cx, JSObject *ctor, ui
     // of object to create, create it, and clamp the return value to an object,
     // among other details. InvokeConstructor does the hard work.
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
         return NULL;
 
     args.calleev().setObject(*ctor);
     args.thisv().setNull();
-    memcpy(args.array(), argv, argc * sizeof(jsval));
+    PodCopy(args.array(), argv, argc);
 
     if (!InvokeConstructor(cx, args))
         return NULL;
 
     if (!args.rval().isObject()) {
         /*
          * Although constructors may return primitives (via proxies), this
          * API is asking for an object, so we report an error.
@@ -6061,17 +6055,17 @@ JSAutoStructuredCloneBuffer::adopt(uint6
 
 bool
 JSAutoStructuredCloneBuffer::copy(const uint64_t *srcData, size_t nbytes, uint32_t version)
 {
     uint64_t *newData = static_cast<uint64_t *>(OffTheBooks::malloc_(nbytes));
     if (!newData)
         return false;
 
-    memcpy(newData, srcData, nbytes);
+    js_memcpy(newData, srcData, nbytes);
 
     clear();
     data_ = newData;
     nbytes_ = nbytes;
     version_ = version;
     return true;
 }
 void
--- a/js/src/jsclone.cpp
+++ b/js/src/jsclone.cpp
@@ -214,17 +214,17 @@ SCInput::readArray(T *p, size_t nelems)
      * Fail if nelems is so huge as to make JS_HOWMANY overflow or if nwords is
      * larger than the remaining data.
      */
     size_t nwords = JS_HOWMANY(nelems, sizeof(uint64_t) / sizeof(T));
     if (nelems + sizeof(uint64_t) / sizeof(T) - 1 < nelems || nwords > size_t(end - point))
         return eof();
 
     if (sizeof(T) == 1) {
-        memcpy(p, point, nelems);
+        js_memcpy(p, point, nelems);
     } else {
         const T *q = (const T *) point;
         const T *qend = q + nelems;
         while (q != qend)
             *p++ = ::SwapBytes(*q++);
     }
     point += nwords;
     return true;
@@ -324,17 +324,17 @@ SCOutput::writeArray(const T *p, size_t 
     size_t start = buf.length();
     if (!buf.growByUninitialized(nwords))
         return false;
 
     buf.back() = 0;  /* zero-pad to an 8-byte boundary */
 
     T *q = (T *) &buf[start];
     if (sizeof(T) == 1) {
-        memcpy(q, p, nelems);
+        js_memcpy(q, p, nelems);
     } else {
         const T *pend = p + nelems;
         while (p != pend)
             *q++ = ::SwapBytes(*p++);
     }
     return true;
 }
 
--- a/js/src/jscrashreport.cpp
+++ b/js/src/jscrashreport.cpp
@@ -101,17 +101,17 @@ GetStack(uint64_t *stack, uint64_t *stac
     regs->bp = context.Ebp;
 #else
     regs->ip = context.Rip;
     regs->sp = context.Rsp;
     regs->bp = context.Rbp;
 #endif
 #endif
 
-    memcpy(buffer, (void *)p, len);
+    js_memcpy(buffer, (void *)p, len);
 
     return true;
 }
 
 #elif 0
 
 #include <unistd.h>
 #include <ucontext.h>
@@ -152,17 +152,17 @@ GetStack(uint64_t *stack, uint64_t *stac
     regs->bp = (uint64_t)context.uc_mcontext.gregs[REG_RBP];
     regs->ip = (uint64_t)context.uc_mcontext.gregs[REG_RIP];
 #elif JS_BITS_PER_WORD == 32
     regs->sp = (uint64_t)context.uc_mcontext.gregs[REG_ESP];
     regs->bp = (uint64_t)context.uc_mcontext.gregs[REG_EBP];
     regs->ip = (uint64_t)context.uc_mcontext.gregs[REG_EIP];
 #endif
 
-    memcpy(buffer, (void *)p, len);
+    js_memcpy(buffer, (void *)p, len);
 
     return true;
 }
 
 #else
 
 static bool
 GetStack(uint64_t *stack, uint64_t *stack_len, CrashRegisters *regs, char *buffer, size_t size)
@@ -225,21 +225,21 @@ void
 Ring::copyBytes(void *data, size_t size)
 {
     if (size >= bufferSize())
         size = bufferSize();
 
     if (offset + size > bufferSize()) {
         size_t first = bufferSize() - offset;
         size_t second = size - first;
-        memcpy(&buffer[offset], data, first);
-        memcpy(buffer, (char *)data + first, second);
+        js_memcpy(&buffer[offset], data, first);
+        js_memcpy(buffer, (char *)data + first, second);
         offset = second;
     } else {
-        memcpy(&buffer[offset], data, size);
+        js_memcpy(&buffer[offset], data, size);
         offset += size;
     }
 }
 
 static bool gInitialized;
 
 static Stack gGCStack(JS_CRASH_STACK_GC);
 static Stack gErrorStack(JS_CRASH_STACK_ERROR);
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -443,17 +443,18 @@ JS_GetFunctionLocalNameArray(JSContext *
     *markp = cx->tempLifoAlloc().mark();
 
     uintptr_t *names = cx->tempLifoAlloc().newArray<uintptr_t>(localNames.length());
     if (!names) {
         js_ReportOutOfMemory(cx);
         return NULL;
     }
 
-    memcpy(names, localNames.begin(), localNames.length() * sizeof(uintptr_t));
+    JS_ASSERT(sizeof(*names) == sizeof(*localNames.begin()));
+    js_memcpy(names, localNames.begin(), localNames.length() * sizeof(*names));
     return names;
 }
 
 extern JS_PUBLIC_API(JSAtom *)
 JS_LocalNameToAtom(uintptr_t w)
 {
     return JS_LOCAL_NAME_TO_ATOM(w);
 }
--- a/js/src/jsdhash.cpp
+++ b/js/src/jsdhash.cpp
@@ -164,17 +164,17 @@ JS_DHashMatchStringKey(JSDHashTable *tab
             strcmp((const char *) stub->key, (const char *) key) == 0);
 }
 
 JS_PUBLIC_API(void)
 JS_DHashMoveEntryStub(JSDHashTable *table,
                       const JSDHashEntryHdr *from,
                       JSDHashEntryHdr *to)
 {
-    memcpy(to, from, table->entrySize);
+    js_memcpy(to, from, table->entrySize);
 }
 
 JS_PUBLIC_API(void)
 JS_DHashClearEntryStub(JSDHashTable *table, JSDHashEntryHdr *entry)
 {
     memset(entry, 0, table->entrySize);
 }
 
--- a/js/src/jsdtoa.cpp
+++ b/js/src/jsdtoa.cpp
@@ -137,17 +137,17 @@ js_dtostr(DtoaState *state, char *buffer
     }
 
     nDigits = numEnd - numBegin;
     JS_ASSERT((size_t) nDigits <= bufferSize - 2);
     if ((size_t) nDigits > bufferSize - 2) {
         return NULL;
     }
 
-    memcpy(buffer + 2, numBegin, nDigits);
+    js_memcpy(buffer + 2, numBegin, nDigits);
     freedtoa(PASS_STATE numBegin);
     numBegin = buffer + 2; /* +2 leaves space for sign and/or decimal point */
     numEnd = numBegin + nDigits;
     *numEnd = '\0';
 
     /* If Infinity, -Infinity, or NaN, return the string regardless of mode. */
     if (decPt != 9999) {
         JSBool exponentialNotation = JS_FALSE;
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -198,52 +198,52 @@ CopyErrorReport(JSContext *cx, JSErrorRe
     cursor += sizeof(JSErrorReport);
 
     if (argsArraySize != 0) {
         copy->messageArgs = (const jschar **)cursor;
         cursor += argsArraySize;
         for (i = 0; report->messageArgs[i]; ++i) {
             copy->messageArgs[i] = (const jschar *)cursor;
             argSize = JS_CHARS_SIZE(report->messageArgs[i]);
-            memcpy(cursor, report->messageArgs[i], argSize);
+            js_memcpy(cursor, report->messageArgs[i], argSize);
             cursor += argSize;
         }
         copy->messageArgs[i] = NULL;
         JS_ASSERT(cursor == (uint8_t *)copy->messageArgs[0] + argsCopySize);
     }
 
     if (report->ucmessage) {
         copy->ucmessage = (const jschar *)cursor;
-        memcpy(cursor, report->ucmessage, ucmessageSize);
+        js_memcpy(cursor, report->ucmessage, ucmessageSize);
         cursor += ucmessageSize;
     }
 
     if (report->uclinebuf) {
         copy->uclinebuf = (const jschar *)cursor;
-        memcpy(cursor, report->uclinebuf, uclinebufSize);
+        js_memcpy(cursor, report->uclinebuf, uclinebufSize);
         cursor += uclinebufSize;
         if (report->uctokenptr) {
             copy->uctokenptr = copy->uclinebuf + (report->uctokenptr -
                                                   report->uclinebuf);
         }
     }
 
     if (report->linebuf) {
         copy->linebuf = (const char *)cursor;
-        memcpy(cursor, report->linebuf, linebufSize);
+        js_memcpy(cursor, report->linebuf, linebufSize);
         cursor += linebufSize;
         if (report->tokenptr) {
             copy->tokenptr = copy->linebuf + (report->tokenptr -
                                               report->linebuf);
         }
     }
 
     if (report->filename) {
         copy->filename = (const char *)cursor;
-        memcpy(cursor, report->filename, filenameSize);
+        js_memcpy(cursor, report->filename, filenameSize);
     }
     JS_ASSERT(cursor + filenameSize == (uint8_t *)copy + mallocSize);
 
     /* HOLD called by the destination error object. */
     copy->originPrincipals = report->originPrincipals;
 
     /* Copy non-pointer members. */
     copy->lineno = report->lineno;
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1591,17 +1591,17 @@ js_fun_call(JSContext *cx, uintN argc, V
     /* Allocate stack space for fval, obj, and the args. */
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
         return JS_FALSE;
 
     /* Push fval, thisv, and the args. */
     args.calleev() = fval;
     args.thisv() = thisv;
-    memcpy(args.array(), argv, argc * sizeof *argv);
+    PodCopy(args.array(), argv, argc);
 
     bool ok = Invoke(cx, args);
     *vp = args.rval();
     return ok;
 }
 
 /* ES5 15.3.4.3 */
 JSBool
@@ -1765,17 +1765,17 @@ CallOrConstructBoundFunction(JSContext *
 
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, argc + argslen, &args))
         return false;
 
     /* 15.3.4.5.1, 15.3.4.5.2 step 4. */
     for (uintN i = 0; i < argslen; i++)
         args[i] = fun->getBoundFunctionArgument(i);
-    memcpy(args.array() + argslen, vp + 2, argc * sizeof(Value));
+    PodCopy(args.array() + argslen, vp + 2, argc);
 
     /* 15.3.4.5.1, 15.3.4.5.2 step 5. */
     args.calleev().setObject(*target);
 
     if (!constructing)
         args.thisv() = boundThis;
 
     if (constructing ? !InvokeConstructor(cx, args) : !Invoke(cx, args))
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -2115,17 +2115,17 @@ TypeCompartment::growPendingArray(JSCont
 {
     unsigned newCapacity = js::Max(unsigned(100), pendingCapacity * 2);
     PendingWork *newArray = (PendingWork *) OffTheBooks::calloc_(newCapacity * sizeof(PendingWork));
     if (!newArray) {
         cx->compartment->types.setPendingNukeTypes(cx);
         return false;
     }
 
-    memcpy(newArray, pendingArray, pendingCount * sizeof(PendingWork));
+    PodCopy(newArray, pendingArray, pendingCount);
     cx->free_(pendingArray);
 
     pendingArray = newArray;
     pendingCapacity = newCapacity;
 
     return true;
 }
 
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -549,17 +549,17 @@ js::Invoke(JSContext *cx, const Value &t
            Value *rval)
 {
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
         return false;
 
     args.calleev() = fval;
     args.thisv() = thisv;
-    memcpy(args.array(), argv, argc * sizeof(Value));
+    PodCopy(args.array(), argv, argc);
 
     if (args.thisv().isObject()) {
         /*
          * We must call the thisObject hook in case we are not called from the
          * interpreter, where a prior bytecode has computed an appropriate
          * |this| already.
          */
         JSObject *thisp = args.thisv().toObject().thisObject(cx);
@@ -618,17 +618,17 @@ bool
 js::InvokeConstructor(JSContext *cx, const Value &fval, uintN argc, Value *argv, Value *rval)
 {
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
         return false;
 
     args.calleev() = fval;
     args.thisv().setMagic(JS_THIS_POISON);
-    memcpy(args.array(), argv, argc * sizeof(Value));
+    PodCopy(args.array(), argv, argc);
 
     if (!InvokeConstructor(cx, args))
         return false;
 
     *rval = args.rval();
     return true;
 }
 
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -36,18 +36,16 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * JavaScript iterators.
  */
-#include <string.h>     /* for memcpy */
-
 #include "mozilla/Util.h"
 
 #include "jstypes.h"
 #include "jsstdint.h"
 #include "jsutil.h"
 #include "jsapi.h"
 #include "jsarray.h"
 #include "jsatom.h"
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -731,17 +731,17 @@ num_toLocaleString(JSContext *cx, uintN 
         JS_ASSERT(tmpDest - buf < buflen);
         *tmpDest++ = *tmpSrc++;
     }
     while (tmpSrc < end) {
         JS_ASSERT(tmpDest - buf + ptrdiff_t(thousandsLength) <= buflen);
         strcpy(tmpDest, rt->thousandsSeparator);
         tmpDest += thousandsLength;
         JS_ASSERT(tmpDest - buf + *tmpGroup <= buflen);
-        memcpy(tmpDest, tmpSrc, *tmpGroup);
+        js_memcpy(tmpDest, tmpSrc, *tmpGroup);
         tmpDest += *tmpGroup;
         tmpSrc += *tmpGroup;
         if (--nrepeat < 0)
             tmpGroup--;
     }
 
     if (*nint == '.') {
         JS_ASSERT(tmpDest - buf + ptrdiff_t(decimalLength) <= buflen);
@@ -973,25 +973,25 @@ InitRuntimeNumberState(JSRuntime *rt)
     size_t groupingSize = strlen(grouping) + 1;
 
     char *storage = static_cast<char *>(OffTheBooks::malloc_(thousandsSeparatorSize +
                                                              decimalPointSize +
                                                              groupingSize));
     if (!storage)
         return false;
 
-    memcpy(storage, thousandsSeparator, thousandsSeparatorSize);
+    js_memcpy(storage, thousandsSeparator, thousandsSeparatorSize);
     rt->thousandsSeparator = storage;
     storage += thousandsSeparatorSize;
 
-    memcpy(storage, decimalPoint, decimalPointSize);
+    js_memcpy(storage, decimalPoint, decimalPointSize);
     rt->decimalSeparator = storage;
     storage += decimalPointSize;
 
-    memcpy(storage, grouping, groupingSize);
+    js_memcpy(storage, grouping, groupingSize);
     rt->numGrouping = grouping;
     return true;
 }
 
 void
 FinishRuntimeNumberState(JSRuntime *rt)
 {
     /*
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3619,19 +3619,19 @@ JSObject::TradeGuts(JSContext *cx, JSObj
         /*
          * If the objects are the same size, then we make no assumptions about
          * whether they have dynamically allocated slots and instead just copy
          * them over wholesale.
          */
         char tmp[tl::Max<sizeof(JSFunction), sizeof(JSObject_Slots16)>::result];
         JS_ASSERT(size <= sizeof(tmp));
 
-        memcpy(tmp, a, size);
-        memcpy(a, b, size);
-        memcpy(b, tmp, size);
+        js_memcpy(tmp, a, size);
+        js_memcpy(a, b, size);
+        js_memcpy(b, tmp, size);
     } else {
         /*
          * If the objects are of differing sizes, use the space we reserved
          * earlier to save the slots from each object and then copy them into
          * the new layout for the other object.
          */
 
         unsigned acap = a->slotSpan();
@@ -3648,19 +3648,19 @@ JSObject::TradeGuts(JSContext *cx, JSObj
             cx->free_(a->slots);
         if (b->hasDynamicSlots())
             cx->free_(b->slots);
 
         void *apriv = a->hasPrivate() ? a->getPrivate() : NULL;
         void *bpriv = b->hasPrivate() ? b->getPrivate() : NULL;
 
         char tmp[sizeof(JSObject)];
-        memcpy(&tmp, a, sizeof tmp);
-        memcpy(a, b, sizeof tmp);
-        memcpy(b, &tmp, sizeof tmp);
+        js_memcpy(&tmp, a, sizeof tmp);
+        js_memcpy(a, b, sizeof tmp);
+        js_memcpy(b, &tmp, sizeof tmp);
 
         if (a->isNative())
             a->shape_->setNumFixedSlots(reserved.newafixed);
         else
             a->shape_ = reserved.newashape;
 
         a->slots = reserved.newaslots;
         a->initSlotRange(0, reserved.bvals.begin(), bcap);
@@ -4313,18 +4313,18 @@ JSObject::growElements(JSContext *cx, ui
             cx->realloc_(getElementsHeader(), oldAllocated * sizeof(Value),
                          newAllocated * sizeof(Value));
         if (!newheader)
             return false;  /* Leave elements as its old size. */
     } else {
         newheader = (ObjectElements *) cx->malloc_(newAllocated * sizeof(Value));
         if (!newheader)
             return false;  /* Ditto. */
-        memcpy(newheader, getElementsHeader(),
-               (ObjectElements::VALUES_PER_HEADER + initlen) * sizeof(Value));
+        js_memcpy(newheader, getElementsHeader(),
+                  (ObjectElements::VALUES_PER_HEADER + initlen) * sizeof(Value));
     }
 
     newheader->capacity = actualCapacity;
     elements = newheader->elements();
 
     Debug_SetValueRangeToCrashOnTouch(elements + initlen, actualCapacity - initlen);
 
     if (Probes::objectResizeActive())
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1560,17 +1560,17 @@ NewObjectCache::fill(EntryIndex entry_, 
 
     JS_ASSERT(!obj->hasDynamicSlots() && !obj->hasDynamicElements());
 
     entry->clasp = clasp;
     entry->key = key;
     entry->kind = kind;
 
     entry->nbytes = obj->structSize();
-    memcpy(&entry->templateObject, obj, entry->nbytes);
+    js_memcpy(&entry->templateObject, obj, entry->nbytes);
 }
 
 inline void
 NewObjectCache::fillProto(EntryIndex entry, Class *clasp, JSObject *proto, gc::AllocKind kind, JSObject *obj)
 {
     JS_ASSERT(!proto->isGlobal());
     JS_ASSERT(obj->getProto() == proto);
     return fill(entry, clasp, proto, kind, obj);
@@ -1593,34 +1593,34 @@ NewObjectCache::fillType(EntryIndex entr
 inline JSObject *
 NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_)
 {
     JS_ASSERT(unsigned(entry_) < ArrayLength(entries));
     Entry *entry = &entries[entry_];
 
     JSObject *obj = js_TryNewGCObject(cx, entry->kind);
     if (obj) {
-        memcpy(obj, &entry->templateObject, entry->nbytes);
+        js_memcpy(obj, &entry->templateObject, entry->nbytes);
         Probes::createObject(cx, obj);
         return obj;
     }
 
     /* Copy the entry to the stack first in case it is purged by a GC. */
     size_t nbytes = entry->nbytes;
     char stackObject[sizeof(JSObject_Slots16)];
     JS_ASSERT(nbytes <= sizeof(stackObject));
-    memcpy(&stackObject, &entry->templateObject, nbytes);
+    js_memcpy(&stackObject, &entry->templateObject, nbytes);
 
     JSObject *baseobj = (JSObject *) stackObject;
     RootShape shapeRoot(cx, (Shape **) baseobj->addressOfShape());
     RootTypeObject typeRoot(cx, (types::TypeObject **) baseobj->addressOfType());
 
     obj = js_NewGCObject(cx, entry->kind);
     if (obj) {
-        memcpy(obj, baseobj, nbytes);
+        js_memcpy(obj, baseobj, nbytes);
         Probes::createObject(cx, obj);
         return obj;
     }
 
     return NULL;
 }
 
 static inline bool
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -1143,37 +1143,37 @@ static inline bool
 UpdateDecompiledText(SprintStack *ss, jsbytecode *pc, ptrdiff_t todo)
 {
     JSPrinter *jp = ss->printer;
 
     if (jp->decompiledOpcodes && jp->decompiled(pc).text == NULL) {
         const char *text = OFF2STR(&ss->sprinter, todo);
         size_t len = strlen(text) + 1;
 
-        const char *ntext = ss->printer->pool.newArrayUninitialized<char>(len);
+        char *ntext = ss->printer->pool.newArrayUninitialized<char>(len);
         if (!ntext) {
             js_ReportOutOfMemory(ss->sprinter.context);
             return false;
         }
 
-        memcpy((char *) ntext, text, len);
-        jp->decompiled(pc).text = ntext;
+        js_memcpy(ntext, text, len);
+        jp->decompiled(pc).text = const_cast<const char *>(ntext);
     }
 
     return true;
 }
 
 static inline const char *
 SprintDupeStr(SprintStack *ss, const char *str)
 {
     size_t len = strlen(str) + 1;
 
     const char *nstr = ss->printer->pool.newArrayUninitialized<char>(len);
     if (nstr) {
-        memcpy((char *) nstr, str, len);
+        js_memcpy((char *) nstr, str, len);
     } else {
         js_ReportOutOfMemory(ss->sprinter.context);
         nstr = "";
     }
 
     return nstr;
 }
 
--- a/js/src/jsprf.cpp
+++ b/js/src/jsprf.cpp
@@ -339,17 +339,17 @@ static int cvt_f(SprintfState *ss, doubl
     char fout[300];
     int amount = fmt1 - fmt0;
 
     JS_ASSERT((amount > 0) && (amount < (int)sizeof(fin)));
     if (amount >= (int)sizeof(fin)) {
         /* Totally bogus % command to sprintf. Just ignore it */
         return 0;
     }
-    memcpy(fin, fmt0, (size_t)amount);
+    js_memcpy(fin, fmt0, (size_t)amount);
     fin[amount] = 0;
 
     /* Convert floating point using the native sprintf code */
 #ifdef DEBUG
     {
         const char *p = fin;
         while (*p) {
             JS_ASSERT(*p != 'L');
@@ -913,17 +913,17 @@ static int dosprintf(SprintfState *ss, c
           case 'E':
           case 'f':
           case 'g':
             u.d = va_arg(ap, double);
             if( nas != NULL ){
                 i = fmt - dolPt;
                 if( i < (int)sizeof( pattern ) ){
                     pattern[0] = '%';
-                    memcpy( &pattern[1], dolPt, (size_t)i );
+                    js_memcpy( &pattern[1], dolPt, (size_t)i );
                     rv = cvt_f(ss, u.d, pattern, &pattern[i+1] );
                 }
             } else
                 rv = cvt_f(ss, u.d, fmt0, fmt);
 
             if (rv < 0) {
                 return rv;
             }
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1136,18 +1136,18 @@ JSScript::NewScriptFromEmitter(JSContext
                        bce->typesetCount, bce->version());
     if (!script)
         return NULL;
 
     bce->bindings.makeImmutable();
 
     JS_ASSERT(script->mainOffset == 0);
     script->mainOffset = prologLength;
-    memcpy(script->code, bce->prologBase(), prologLength * sizeof(jsbytecode));
-    memcpy(script->main(), bce->base(), mainLength * sizeof(jsbytecode));
+    PodCopy<jsbytecode>(script->code, bce->prologBase(), prologLength);
+    PodCopy<jsbytecode>(script->main(), bce->base(), mainLength);
     nfixed = bce->inFunction()
              ? bce->bindings.countVars()
              : bce->sharpSlots();
     JS_ASSERT(nfixed < SLOTNO_LIMIT);
     script->nfixed = uint16_t(nfixed);
     js_InitAtomMap(cx, bce->atomIndices.getMap(), script->atoms);
 
     filename = bce->parser->tokenStream.getFilename();
@@ -1204,32 +1204,32 @@ JSScript::NewScriptFromEmitter(JSContext
         script->usesEval = true;
     if (bce->flags & TCF_FUN_USES_ARGUMENTS)
         script->usesArguments = true;
     if (bce->flags & TCF_HAS_SINGLETONS)
         script->hasSingletons = true;
 
     if (bce->hasUpvarIndices()) {
         JS_ASSERT(bce->upvarIndices->count() <= bce->upvarMap.length());
-        memcpy(script->upvars()->vector, bce->upvarMap.begin(),
-               bce->upvarIndices->count() * sizeof(bce->upvarMap[0]));
+        PodCopy<UpvarCookie>(script->upvars()->vector, bce->upvarMap.begin(),
+                             bce->upvarIndices->count());
         bce->upvarIndices->clear();
         bce->upvarMap.clear();
     }
 
     if (bce->globalUses.length()) {
-        memcpy(script->globals()->vector, &bce->globalUses[0],
-               bce->globalUses.length() * sizeof(GlobalSlotArray::Entry));
+        PodCopy<GlobalSlotArray::Entry>(script->globals()->vector, &bce->globalUses[0],
+                                        bce->globalUses.length());
     }
 
     if (script->nClosedArgs)
-        memcpy(script->closedSlots, &bce->closedArgs[0], script->nClosedArgs * sizeof(uint32_t));
+        PodCopy<uint32_t>(script->closedSlots, &bce->closedArgs[0], script->nClosedArgs);
     if (script->nClosedVars) {
-        memcpy(&script->closedSlots[script->nClosedArgs], &bce->closedVars[0],
-               script->nClosedVars * sizeof(uint32_t));
+        PodCopy<uint32_t>(&script->closedSlots[script->nClosedArgs], &bce->closedVars[0],
+                          script->nClosedVars);
     }
 
     script->bindings.transfer(cx, &bce->bindings);
 
     fun = NULL;
     if (bce->inFunction()) {
         /*
          * We initialize fun->script() to be the script constructed above
@@ -1710,17 +1710,17 @@ js_CloneScript(JSContext *cx, JSScript *
     }
 
     return newScript;
 }
 
 void
 JSScript::copyClosedSlotsTo(JSScript *other)
 {
-    memcpy(other->closedSlots, closedSlots, nClosedArgs + nClosedVars);
+    js_memcpy(other->closedSlots, closedSlots, nClosedArgs + nClosedVars);
 }
 
 bool
 JSScript::ensureHasDebug(JSContext *cx)
 {
     if (debug)
         return true;
 
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -3263,17 +3263,17 @@ js_NewStringCopyZ(JSContext *cx, const j
     size_t n = js_strlen(s);
     if (JSShortString::lengthFits(n))
         return NewShortString(cx, s, n);
 
     size_t m = (n + 1) * sizeof(jschar);
     jschar *news = (jschar *) cx->malloc_(m);
     if (!news)
         return NULL;
-    memcpy(news, s, m);
+    js_memcpy(news, s, m);
     JSFixedString *str = js_NewString(cx, news, n);
     if (!str)
         cx->free_(news);
     return str;
 }
 
 JSFixedString *
 js_NewStringCopyZ(JSContext *cx, const char *s)
--- a/js/src/jsstr.h
+++ b/js/src/jsstr.h
@@ -41,16 +41,17 @@
 #define jsstr_h___
 
 #include <ctype.h>
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jsprvtd.h"
 #include "jslock.h"
 #include "jscell.h"
+#include "jsutil.h"
 
 #include "js/HashTable.h"
 #include "vm/Unicode.h"
 
 namespace js {
 
 /* Implemented in jsstrinlines.h */
 class StringBuffer;
@@ -210,17 +211,21 @@ extern size_t
 js_strlen(const jschar *s);
 
 extern jschar *
 js_strchr(const jschar *s, jschar c);
 
 extern jschar *
 js_strchr_limit(const jschar *s, jschar c, const jschar *limit);
 
-#define js_strncpy(t, s, n)     memcpy((t), (s), (n) * sizeof(jschar))
+static JS_ALWAYS_INLINE void
+js_strncpy(jschar *dst, const jschar *src, size_t nelem)
+{
+    return js::PodCopy(dst, src, nelem);
+}
 
 namespace js {
 
 /*
  * Inflate bytes to jschars. Return null on error, otherwise return the jschar
  * or byte vector that was malloc'ed. length is updated to the length of the
  * new string (in jschars).
  */
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -1794,17 +1794,17 @@ class TypedArrayTemplate
         JS_ASSERT(offset <= getLength(thisTypedArrayObj));
         JS_ASSERT(getLength(tarray) <= getLength(thisTypedArrayObj) - offset);
         if (getBuffer(tarray) == getBuffer(thisTypedArrayObj))
             return copyFromWithOverlap(cx, thisTypedArrayObj, tarray, offset);
 
         NativeType *dest = static_cast<NativeType*>((void*)getDataOffset(thisTypedArrayObj)) + offset;
 
         if (getType(tarray) == getType(thisTypedArrayObj)) {
-            memcpy(dest, getDataOffset(tarray), getByteLength(tarray));
+            js_memcpy(dest, getDataOffset(tarray), getByteLength(tarray));
             return true;
         }
 
         uintN srclen = getLength(tarray);
         switch (getType(tarray)) {
           case TypedArray::TYPE_INT8: {
             int8_t *src = static_cast<int8_t*>(getDataOffset(tarray));
             for (uintN i = 0; i < srclen; ++i)
@@ -1874,17 +1874,17 @@ class TypedArrayTemplate
             return true;
         }
 
         // We have to make a copy of the source array here, since
         // there's overlap, and we have to convert types.
         void *srcbuf = cx->malloc_(getLength(tarray));
         if (!srcbuf)
             return false;
-        memcpy(srcbuf, getDataOffset(tarray), getByteLength(tarray));
+        js_memcpy(srcbuf, getDataOffset(tarray), getByteLength(tarray));
 
         switch (getType(tarray)) {
           case TypedArray::TYPE_INT8: {
             int8_t *src = (int8_t*) srcbuf;
             for (uintN i = 0; i < getLength(tarray); ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -178,17 +178,17 @@ JS_BasicStatsAccum(JSBasicStats *bs, uin
             if (newscale != oldscale) {
                 uint32_t newhist[11], newbin;
 
                 PodArrayZero(newhist);
                 for (bin = 0; bin <= 10; bin++) {
                     newbin = ValToBin(newscale, BinToVal(oldscale, bin));
                     newhist[newbin] += bs->hist[bin];
                 }
-                memcpy(bs->hist, newhist, sizeof bs->hist);
+                js_memcpy(bs->hist, newhist, sizeof bs->hist);
                 bs->logscale = newscale;
             }
         }
     }
 
     bin = ValToBin(bs->logscale, val);
     ++bs->hist[bin];
 }
--- a/js/src/jsutil.h
+++ b/js/src/jsutil.h
@@ -46,16 +46,27 @@
 
 #include "mozilla/Attributes.h"
 
 #include "js/Utility.h"
 
 /* Forward declarations. */
 struct JSContext;
 
+static JS_ALWAYS_INLINE void *
+js_memcpy(void *dst_, const void *src_, size_t len)
+{
+    char *dst = (char *) dst_;
+    const char *src = (const char *) src_;
+    JS_ASSERT_IF(dst >= src, size_t(dst - src) >= len);
+    JS_ASSERT_IF(src >= dst, size_t(src - dst) >= len);
+
+    return memcpy(dst, src, len);
+}
+
 #ifdef __cplusplus
 namespace js {
 
 template <class T>
 class AlignedPtrAndFlag
 {
     uintptr_t bits;
 
@@ -283,17 +294,17 @@ JS_ALWAYS_INLINE static void
 PodZero(T *t, size_t nelem)
 {
     /*
      * This function is often called with 'nelem' small; we use an
      * inline loop instead of calling 'memset' with a non-constant
      * length.  The compiler should inline the memset call with constant
      * size, though.
      */
-    for (size_t i = 0; i < nelem; ++i, ++t)
+    for (T *end = t + nelem; t != end; ++t)
         memset(t, 0, sizeof(T));
 }
 
 /*
  * Arrays implicitly convert to pointers to their first element, which is
  * dangerous when combined with the above PodZero definitions. Adding an
  * overload for arrays is ambiguous, so we need another identifier. The
  * ambiguous overload is left to catch mistaken uses of PodZero; if you get a
@@ -306,25 +317,36 @@ template <class T, size_t N>
 JS_ALWAYS_INLINE static void
 PodArrayZero(T (&t)[N])
 {
     memset(t, 0, N * sizeof(T));
 }
 
 template <class T>
 JS_ALWAYS_INLINE static void
+PodAssign(T *dst, const T *src)
+{
+    js_memcpy((char *) dst, (const char *) src, sizeof(T));
+}
+
+template <class T>
+JS_ALWAYS_INLINE static void
 PodCopy(T *dst, const T *src, size_t nelem)
 {
     /* Cannot find portable word-sized abs(). */
     JS_ASSERT_IF(dst >= src, size_t(dst - src) >= nelem);
     JS_ASSERT_IF(src >= dst, size_t(src - dst) >= nelem);
 
     if (nelem < 128) {
+        /*
+         * Avoid using operator= in this loop, as it may have been
+         * intentionally deleted by the POD type.
+         */
         for (const T *srcend = src + nelem; src != srcend; ++src, ++dst)
-            *dst = *src;
+            PodAssign(dst, src);
     } else {
         memcpy(dst, src, nelem * sizeof(T));
     }
 }
 
 template <class T>
 JS_ALWAYS_INLINE static bool
 PodEqual(T *one, T *two, size_t len)
--- a/js/src/jsxdrapi.cpp
+++ b/js/src/jsxdrapi.cpp
@@ -130,26 +130,26 @@ mem_set32(JSXDRState *xdr, uint32_t *lp)
     MEM_INCR(xdr, 4);
     return JS_TRUE;
 }
 
 static JSBool
 mem_getbytes(JSXDRState *xdr, char *bytes, uint32_t len)
 {
     MEM_LEFT(xdr, len);
-    memcpy(bytes, MEM_DATA(xdr), len);
+    js_memcpy(bytes, MEM_DATA(xdr), len);
     MEM_INCR(xdr, len);
     return JS_TRUE;
 }
 
 static JSBool
 mem_setbytes(JSXDRState *xdr, char *bytes, uint32_t len)
 {
     MEM_NEED(xdr, len);
-    memcpy(MEM_DATA(xdr), bytes, len);
+    js_memcpy(MEM_DATA(xdr), bytes, len);
     MEM_INCR(xdr, len);
     return JS_TRUE;
 }
 
 static void *
 mem_raw(JSXDRState *xdr, uint32_t len)
 {
     void *data;
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3763,17 +3763,17 @@ Serialize(JSContext *cx, uintN argc, jsv
 
     JSObject *arrayobj = js_CreateTypedArray(cx, TypedArray::TYPE_UINT8, nbytes);
     if (!arrayobj) {
         JS_free(cx, datap);
         return false;
     }
     JSObject *array = TypedArray::getTypedArray(arrayobj);
     JS_ASSERT((uintptr_t(TypedArray::getDataOffset(array)) & 7) == 0);
-    memcpy(TypedArray::getDataOffset(array), datap, nbytes);
+    js_memcpy(TypedArray::getDataOffset(array), datap, nbytes);
     JS_free(cx, datap);
     JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(arrayobj));
     return true;
 }
 
 JSBool
 Deserialize(JSContext *cx, uintN argc, jsval *vp)
 {