byteArray_prims.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.32 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 # include "incls/_precompiled.incl"
00025 # include "incls/_byteArray_prims.cpp.incl"
00026 
00027 TRACE_FUNC(TraceByteArrayPrims, "byteArray")
00028 
00029 int byteArrayPrimitives::number_of_calls;
00030 
00031 #define ASSERT_RECEIVER assert(receiver->is_byteArray(), "receiver must be byte array")
00032 
00033 PRIM_DECL_2(byteArrayPrimitives::allocateSize, oop receiver, oop argument) {
00034   PROLOGUE_2("allocateSize", receiver, argument)
00035   assert(receiver->is_klass() && klassOop(receiver)->klass_part()->oop_is_byteArray(),
00036         "receiver must byte array class");
00037   if (!argument->is_smi())
00038     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00039 
00040   if (smiOop(argument)->value() < 0)
00041     return markSymbol(vmSymbols::negative_size());
00042 
00043   klassOop k        = klassOop(receiver);
00044   int      ni_size  = k->klass_part()->non_indexable_size();
00045   int      obj_size = ni_size + 1 + roundTo(smiOop(argument)->value(), oopSize) / oopSize;
00046   // allocate
00047   byteArrayOop obj = as_byteArrayOop(Universe::allocate(obj_size, (memOop*)&k));
00048   // header
00049   memOop(obj)->initialize_header(true, k);
00050   // instance variables
00051   memOop(obj)->initialize_body(memOopDesc::header_size(), ni_size);
00052   // indexables
00053   oop* base = (oop*) obj->addr();
00054   oop* end  = base + obj_size;
00055   // %optimized 'obj->set_length(size)'
00056   base[ni_size] = argument;
00057   // %optimized 'for (int index = 1; index <= size; index++)
00058   //               obj->byte_at_put(index, '\000')'
00059   base = &base[ni_size+1];
00060   while (base < end) *base++ = (oop) 0;
00061   return obj;
00062 }
00063 
00064 PRIM_DECL_1(byteArrayPrimitives::size, oop receiver) {
00065   PROLOGUE_1("size", receiver);
00066   ASSERT_RECEIVER;
00067   // do the operation
00068   return as_smiOop(byteArrayOop(receiver)->length());
00069 }
00070 
00071 PRIM_DECL_2(byteArrayPrimitives::at, oop receiver, oop index) {
00072   PROLOGUE_2("at", receiver, index);
00073   ASSERT_RECEIVER;
00074 
00075   // check index type
00076   if (!index->is_smi())
00077     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00078 
00079   // check index value
00080   if (!byteArrayOop(receiver)->is_within_bounds(smiOop(index)->value()))
00081      return markSymbol(vmSymbols::out_of_bounds());
00082 
00083   // do the operation
00084   return as_smiOop(byteArrayOop(receiver)->byte_at(smiOop(index)->value()));
00085 }
00086 
00087 PRIM_DECL_3(byteArrayPrimitives::atPut, oop receiver, oop index, oop value) {
00088   PROLOGUE_3("atPut", receiver, index, value);
00089   ASSERT_RECEIVER;
00090 
00091   // check index type
00092   if (!index->is_smi())
00093     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00094 
00095   // check index type
00096   if (!value->is_smi())
00097     return markSymbol(vmSymbols::second_argument_has_wrong_type());
00098 
00099   // check index value
00100   if (!byteArrayOop(receiver)->is_within_bounds(smiOop(index)->value()))
00101      return markSymbol(vmSymbols::out_of_bounds());
00102 
00103   // check value range (must be byte)
00104   unsigned int v = (unsigned int) smiOop(value)->value();
00105   if (v  >= (1<<8))
00106     return markSymbol(vmSymbols::value_out_of_range());
00107 
00108   // do the operation
00109   byteArrayOop(receiver)->byte_at_put(smiOop(index)->value(), v);
00110   return receiver;
00111 }
00112 
00113 PRIM_DECL_2(byteArrayPrimitives::compare, oop receiver, oop argument) {
00114   PROLOGUE_2("comare", receiver, argument);
00115   ASSERT_RECEIVER;
00116 
00117   if( receiver == argument)
00118     return as_smiOop(0);
00119 
00120   if (argument->is_byteArray())
00121     return as_smiOop(byteArrayOop(receiver)->compare(byteArrayOop(argument)));
00122 
00123   if (argument->is_doubleByteArray())
00124     return as_smiOop(byteArrayOop(receiver)->compare_doubleBytes(doubleByteArrayOop(argument)));
00125 
00126   return markSymbol(vmSymbols::first_argument_has_wrong_type());
00127 }
00128 
00129 PRIM_DECL_1(byteArrayPrimitives::intern, oop receiver) {
00130   PROLOGUE_1("intern", receiver);
00131   ASSERT_RECEIVER;
00132 
00133   return Universe::symbol_table->lookup(byteArrayOop(receiver)->chars(),
00134                                         byteArrayOop(receiver)->length());
00135 }
00136 
00137 PRIM_DECL_2(byteArrayPrimitives::characterAt, oop receiver, oop index) {
00138   PROLOGUE_2("characterAt", receiver, index);
00139   ASSERT_RECEIVER;
00140 
00141   // check index type
00142   if (!index->is_smi())
00143     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00144 
00145   // range check
00146   if (!byteArrayOop(receiver)->is_within_bounds(smiOop(index)->value()))
00147      return markSymbol(vmSymbols::out_of_bounds());
00148 
00149   // fetch byte
00150   int byte = byteArrayOop(receiver)->byte_at(smiOop(index)->value());
00151   
00152   // return the n+1'th element in asciiCharacter
00153   return Universe::asciiCharacters()->obj_at(byte+1);
00154 }
00155 
00156 PRIM_DECL_2(byteArrayPrimitives::at_all_put, oop receiver, oop value) {
00157   PROLOGUE_2("at_all_put", receiver, value);
00158   ASSERT_RECEIVER;
00159 
00160   // check index type
00161   if (!value->is_smi())
00162     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00163 
00164   // check value range (must be byte)
00165   unsigned int v = (unsigned int) smiOop(value)->value();
00166   if (v  >= (1<<8))
00167     return markSymbol(vmSymbols::value_out_of_range());
00168 
00169   int length = byteArrayOop(receiver)->length();
00170   for (int index = 1; index <= length; index++) {
00171     byteArrayOop(receiver)->byte_at_put(index, v);
00172   }
00173   return receiver;
00174 }
00175 
00176 // LargeIntegers primitives
00177 
00178 oop simplified(byteArrayOop result) {
00179   // Tries to simplify result, a large integer, into a small integer if possible.
00180   bool ok;
00181   oop smi_result = result->number().as_smi(ok);
00182   return ok ? smi_result : result;
00183 }
00184 
00185 PRIM_DECL_2(byteArrayPrimitives::largeIntegerFromSmallInteger, oop receiver, oop number) {
00186   PROLOGUE_2("largeIntegerFromSmallInteger", receiver, number);
00187   assert(receiver->is_klass() && klassOop(receiver)->klass_part()->oop_is_byteArray(), "just checking");
00188 
00189   // Check arguments
00190   if (!number->is_smi()) return markSymbol(vmSymbols::second_argument_has_wrong_type());
00191 
00192   BlockScavenge bs;
00193   int           i = smiOop(number)->value();
00194   byteArrayOop  z;
00195 
00196   z = byteArrayOop(klassOop(receiver)->klass_part()->allocateObjectSize(IntegerOps::int_to_Integer_result_size_in_bytes(i)));
00197   IntegerOps::int_to_Integer(i, z->number());
00198   return z;
00199 }
00200 
00201 PRIM_DECL_2(byteArrayPrimitives::largeIntegerFromDouble, oop receiver, oop number) {
00202   PROLOGUE_2("largeIntegerFromDouble", receiver, number);
00203   assert(receiver->is_klass() && klassOop(receiver)->klass_part()->oop_is_byteArray(), "just checking");
00204 
00205   if (!number->is_double()) return markSymbol(vmSymbols::first_argument_has_wrong_type());
00206 
00207   BlockScavenge bs;
00208   double x = doubleOop(number)->value();
00209   byteArrayOop z;
00210 
00211   z = byteArrayOop(klassOop(receiver)->klass_part()->allocateObjectSize(IntegerOps::double_to_Integer_result_size_in_bytes(x)));
00212   IntegerOps::double_to_Integer(x, z->number());
00213   return z;
00214 }
00215 
00216 PRIM_DECL_3(byteArrayPrimitives::largeIntegerFromString, oop receiver, oop argument, oop base) {
00217   PROLOGUE_3("largeIntegerFromString", receiver, argument, base);
00218   assert(receiver->is_klass() && klassOop(receiver)->klass_part()->oop_is_byteArray(), "just checking");
00219 
00220   if (!argument->is_byteArray()) return markSymbol(vmSymbols::first_argument_has_wrong_type ());
00221   if (!base->is_smi()          ) return markSymbol(vmSymbols::second_argument_has_wrong_type());
00222 
00223   BlockScavenge bs;
00224 
00225   byteArrayOop x = byteArrayOop(argument);
00226   byteArrayOop z;
00227 
00228   z = byteArrayOop(x->klass()->klass_part()->allocateObjectSize(IntegerOps::string_to_Integer_result_size_in_bytes(x->chars(), smiOop(base)->value())));
00229   IntegerOps::string_to_Integer(x->chars(), smiOop(base)->value(), z->number());
00230   return z;
00231 }
00232 
00233 PRIM_DECL_2(byteArrayPrimitives::largeIntegerAdd, oop receiver, oop argument) {
00234   PROLOGUE_2("largeIntegerAdd", receiver, argument);
00235   ASSERT_RECEIVER;
00236 
00237   if (!argument->is_byteArray())
00238     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00239 
00240   BlockScavenge bs;
00241 
00242   byteArrayOop x = byteArrayOop(receiver);
00243   byteArrayOop y = byteArrayOop(argument);
00244   byteArrayOop z;
00245 
00246   if (!x->number().is_valid() || !y->number().is_valid()) return markSymbol(vmSymbols::argument_is_invalid());
00247 
00248   z = byteArrayOop(x->klass()->klass_part()->allocateObjectSize(IntegerOps::add_result_size_in_bytes(x->number(), y->number())));
00249   x = byteArrayOop(receiver);
00250   y = byteArrayOop(argument);
00251   IntegerOps::add(x->number(), y->number(), z->number());
00252   return simplified(z);
00253 }
00254 
00255 PRIM_DECL_2(byteArrayPrimitives::largeIntegerSubtract, oop receiver, oop argument) {
00256   PROLOGUE_2("largeIntegerSubtract", receiver, argument);
00257   ASSERT_RECEIVER;
00258 
00259   if (!argument->is_byteArray())
00260     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00261 
00262   BlockScavenge bs;
00263 
00264   byteArrayOop x = byteArrayOop(receiver);
00265   byteArrayOop y = byteArrayOop(argument);
00266   byteArrayOop z;
00267 
00268   if (!x->number().is_valid() || !y->number().is_valid()) return markSymbol(vmSymbols::argument_is_invalid());
00269 
00270   z = byteArrayOop(x->klass()->klass_part()->allocateObjectSize(IntegerOps::sub_result_size_in_bytes(x->number(), y->number())));
00271   x = byteArrayOop(receiver);
00272   y = byteArrayOop(argument);
00273   IntegerOps::sub(x->number(), y->number(), z->number());
00274   return simplified(z);
00275 }
00276 
00277 PRIM_DECL_2(byteArrayPrimitives::largeIntegerMultiply, oop receiver, oop argument) {
00278   PROLOGUE_2("largeIntegerMultiply", receiver, argument);
00279   ASSERT_RECEIVER;
00280 
00281   if (!argument->is_byteArray())
00282     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00283 
00284   BlockScavenge bs;
00285 
00286   byteArrayOop x = byteArrayOop(receiver);
00287   byteArrayOop y = byteArrayOop(argument);
00288   byteArrayOop z;
00289 
00290   if (!x->number().is_valid() || !y->number().is_valid()) return markSymbol(vmSymbols::argument_is_invalid());
00291 
00292   z = byteArrayOop(x->klass()->klass_part()->allocateObjectSize(IntegerOps::mul_result_size_in_bytes(x->number(), y->number())));
00293   x = byteArrayOop(receiver);
00294   y = byteArrayOop(argument);
00295   IntegerOps::mul(x->number(), y->number(), z->number());
00296   return simplified(z);
00297 }
00298 
00299 PRIM_DECL_2(byteArrayPrimitives::largeIntegerDiv, oop receiver, oop argument) {
00300   PROLOGUE_2("largeIntegerDiv", receiver, argument);
00301   ASSERT_RECEIVER;
00302 
00303   if (!argument->is_byteArray())
00304     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00305 
00306   BlockScavenge bs;
00307 
00308   byteArrayOop x = byteArrayOop(receiver);
00309   byteArrayOop y = byteArrayOop(argument);
00310   byteArrayOop z;
00311 
00312   if (!x->number().is_valid() || !y->number().is_valid()) return markSymbol(vmSymbols::argument_is_invalid());
00313   if (y->number().is_zero()                             ) return markSymbol(vmSymbols::division_by_zero   ());
00314 
00315   z = byteArrayOop(x->klass()->klass_part()->allocateObjectSize(IntegerOps::div_result_size_in_bytes(x->number(), y->number())));
00316   x = byteArrayOop(receiver);
00317   y = byteArrayOop(argument);
00318   IntegerOps::div(x->number(), y->number(), z->number());
00319   return simplified(z);
00320 }
00321 
00322 PRIM_DECL_2(byteArrayPrimitives::largeIntegerMod, oop receiver, oop argument) {
00323   PROLOGUE_2("largeIntegerMod", receiver, argument);
00324   ASSERT_RECEIVER;
00325 
00326   if (!argument->is_byteArray())
00327     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00328 
00329   BlockScavenge bs;
00330 
00331   byteArrayOop x = byteArrayOop(receiver);
00332   byteArrayOop y = byteArrayOop(argument);
00333   byteArrayOop z;
00334 
00335   if (!x->number().is_valid() || !y->number().is_valid()) return markSymbol(vmSymbols::argument_is_invalid());
00336   if (y->number().is_zero()                             ) return markSymbol(vmSymbols::division_by_zero   ());
00337 
00338   z = byteArrayOop(x->klass()->klass_part()->allocateObjectSize(IntegerOps::mod_result_size_in_bytes(x->number(), y->number())));
00339   x = byteArrayOop(receiver);
00340   y = byteArrayOop(argument);
00341   IntegerOps::mod(x->number(), y->number(), z->number());
00342   return simplified(z);
00343 }
00344 
00345 PRIM_DECL_2(byteArrayPrimitives::largeIntegerCompare, oop receiver, oop argument) {
00346   PROLOGUE_2("largeIntegerCompare", receiver, argument);
00347   ASSERT_RECEIVER;
00348 
00349   // Check argument
00350   if (!argument->is_byteArray())
00351     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00352 
00353   BlockScavenge bs;
00354 
00355   byteArrayOop x = byteArrayOop(receiver);
00356   byteArrayOop y = byteArrayOop(argument);
00357 
00358   if (!x->number().is_valid() || !y->number().is_valid()) return markSymbol(vmSymbols::argument_is_invalid());
00359 
00360   int res = IntegerOps::cmp(x->number(), y->number());
00361   if (res < 0) return as_smiOop(-1);
00362   if (res > 0) return as_smiOop(1);
00363   return as_smiOop(0);
00364 }
00365 
00366 PRIM_DECL_1(byteArrayPrimitives::largeIntegerToFloat, oop receiver) {
00367   PROLOGUE_1("largeIntegerToFloat", receiver);
00368   ASSERT_RECEIVER;
00369 
00370   bool ok;
00371   double result = byteArrayOop(receiver)->number().as_double(ok);
00372 
00373   if (!ok) return markSymbol(vmSymbols::conversion_failed());
00374 
00375   BlockScavenge bs;
00376   return oopFactory::new_double(result);
00377 }
00378 
00379 PRIM_DECL_2(byteArrayPrimitives::largeIntegerToString, oop receiver, oop base) {
00380   PROLOGUE_1("largeIntegerToString", receiver);
00381   ASSERT_RECEIVER;
00382 
00383   // Check argument
00384   if (!base->is_smi())
00385     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00386 
00387   BlockScavenge bs;
00388 
00389   byteArrayOop x = byteArrayOop(receiver);
00390   int length = IntegerOps::Integer_to_string_result_size_in_bytes(x->number(), smiOop(base)->value());
00391 
00392   byteArrayOop result = oopFactory::new_byteArray(length);
00393 
00394   IntegerOps::Integer_to_string(x->number(), smiOop(base)->value(), result->chars());
00395   return result;
00396 }
00397 
00398 PRIM_DECL_1(byteArrayPrimitives::hash, oop receiver) {
00399   PROLOGUE_1("hash", receiver);
00400   ASSERT_RECEIVER;
00401   return as_smiOop(byteArrayOop(receiver)->hash_value());
00402 }

Generated on Mon Oct 9 13:37:03 2006 for Strongtalk VM by  doxygen 1.4.7